From 069a441b4fdb07f200f952a66c14a8f405a98bed Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 17 Jun 2024 14:42:05 -0500 Subject: [PATCH 001/500] cleanup pt 2 --- .../command/starship/MiscStarshipCommands.kt | 3 + .../server/features/machine/AreaShields.kt | 2 +- .../server/features/multiblock/Multiblocks.kt | 71 +++---------------- .../type/areashield/AreaShield10.kt | 2 +- .../type/areashield/AreaShield20.kt | 2 +- .../type/areashield/AreaShield30.kt | 2 +- .../multiblock/type/areashield/AreaShield5.kt | 2 +- .../type/crafting/MultiblockRecipes.kt | 24 +++---- .../recipe/FurnaceMultiblockRecipe.kt | 8 +-- .../recipe/ProcessingMultiblockRecipe.kt | 8 +-- .../type/crafting/result/ActionResult.kt | 2 +- .../type/crafting/result/ItemResult.kt | 2 +- .../type/crafting/result/MultiRecipeResult.kt | 4 +- .../crafting/result/MultiblockRecipeResult.kt | 4 +- .../crafting/result/ProgressItemResult.kt | 2 +- .../type/crafting/result/ResourceResult.kt | 4 +- .../type/crafting/result/SoundResult.kt | 4 +- .../type/industry/FabricatorMultiblock.kt | 2 - .../type/industry/PlatePressMultiblock.kt | 4 +- 19 files changed, 49 insertions(+), 103 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index f8a9905e82..f2395490d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -34,8 +34,11 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.util.Pos import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.client.display.HudIcons +import net.horizonsend.ion.server.features.misc.HyperspaceBeaconManager +import net.horizonsend.ion.server.features.misc.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic +import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.space.Space diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index b312d9345f..2d0508a56a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -205,7 +205,7 @@ object AreaShields : IonServerComponent() { val block = shieldLocation.block if (!block.type.isWallSign) continue val sign = block.getState(false) as Sign - val multiblock = Multiblocks[sign] as? AreaShield ?: continue + val multiblock = Multiblocks[sign] as? net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield ?: continue if (multiblock.radius != areaShields[shieldLocation]) continue if (PowerMachines.getPower(sign) > 0) event.isCancelled = true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index a6891a8e56..ea8eb737b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -3,14 +3,8 @@ package net.horizonsend.ion.server.features.multiblock import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Bottom -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4BottomMirrored -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Side -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4SideMirrored -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Top -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4TopMirrored -import net.horizonsend.ion.server.features.multiblock.starshipweapon.turret.BottomIonTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.starshipweapon.turret.TopIonTurretMultiblock +import net.horizonsend.ion.server.features.achievements.Achievement +import net.horizonsend.ion.server.features.achievements.rewardAchievement import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock @@ -19,11 +13,8 @@ import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield30 import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield5 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1Mirrored import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2Mirrored import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3Mirrored import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier3 @@ -34,11 +25,8 @@ import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannon import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1Mirrored import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2Mirrored import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3Mirrored import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier3 @@ -64,35 +52,27 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMu import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1SideMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1Top -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1TopMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2SideMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2Top -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2TopMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3SideMirrored import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Top -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3TopMirrored +import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier4Bottom +import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier4Side +import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier4Top import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LargeTractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock @@ -117,14 +97,10 @@ import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFur import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock @@ -132,12 +108,9 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event. import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.FireWaveWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.FlamethrowerStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.GazeStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.HorizontalPumpkinCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.MiniPhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.PumpkinCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.SkullThrowerStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.SonicMissileWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIHeavyLaserStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIPhaserStarshipWeaponMultiblock @@ -153,16 +126,17 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.P import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockTop import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomHeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomIonTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomLightTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomQuadTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomTriTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopHeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopIonTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopLightTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopQuadTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopTriTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretBaseMultiblock import net.horizonsend.ion.server.features.progression.achievements.Achievement -import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text @@ -231,13 +205,9 @@ object Multiblocks : IonServerComponent() { CarbonProcessorMultiblock, CarbonPrinterMultiblock, - CarbonPrinterMultiblockMirrored, TechnicalPrinterMultiblock, - TechnicalPrinterMultiblockMirrored, GlassPrinterMultiblock, - GlassPrinterMultiblockMirrored, ArmorPrinterMultiblock, - ArmorPrinterMultiblockMirrored, DisconnectedDockingTubeMultiblock, ConnectedDockingTubeMultiblock, @@ -245,7 +215,6 @@ object Multiblocks : IonServerComponent() { CryoPodMultiblock, FuelTankMultiblock, MagazineMultiblock, - MagazineMultiblockMirrored, AirlockMultiblock, ExpandableAirlock, TractorBeamMultiblock, @@ -254,11 +223,8 @@ object Multiblocks : IonServerComponent() { ShipFactoryMultiblock, DrillMultiblockTier1, - DrillMultiblockTier1Mirrored, DrillMultiblockTier2, - DrillMultiblockTier2Mirrored, DrillMultiblockTier3, - DrillMultiblockTier3Mirrored, StandardGravityWellMultiblock, AmplifiedGravityWellMultiblock, @@ -301,34 +267,20 @@ object Multiblocks : IonServerComponent() { PhaserStarshipWeaponMultiblock, MiniPhaserStarshipWeaponMultiblock, SonicMissileWeaponMultiblock, - FireWaveWeaponMultiblock, DecomposerMultiblock, DisposalMultiblock, - DisposalMultiblockMirrored, MiningLaserMultiblockTier1Top, - MiningLaserMultiblockTier1TopMirrored, MiningLaserMultiblockTier1Bottom, - MiningLaserMultiblockTier1BottomMirrored, MiningLaserMultiblockTier1Side, - MiningLaserMultiblockTier1SideMirrored, MiningLaserMultiblockTier2Top, - MiningLaserMultiblockTier2TopMirrored, MiningLaserMultiblockTier2Bottom, - MiningLaserMultiblockTier2BottomMirrored, MiningLaserMultiblockTier2Side, - MiningLaserMultiblockTier2SideMirrored, MiningLaserMultiblockTier3Top, - MiningLaserMultiblockTier3TopMirrored, MiningLaserMultiblockTier3Bottom, - MiningLaserMultiblockTier3BottomMirrored, MiningLaserMultiblockTier3Side, - MiningLaserMultiblockTier3SideMirrored, MiningLaserMultiblockTier4Top, - MiningLaserMultiblockTier4TopMirrored, MiningLaserMultiblockTier4Bottom, - MiningLaserMultiblockTier4BottomMirrored, MiningLaserMultiblockTier4Side, - MiningLaserMultiblockTier4SideMirrored, TopArsenalStarshipWeaponMultiblock, BottomArsenalStarshipWeaponMultiblock, @@ -340,20 +292,15 @@ object Multiblocks : IonServerComponent() { LandingGearMultiblock, AutoCrafterMultiblockTier1, - AutoCrafterMultiblockTier1Mirrored, AutoCrafterMultiblockTier2, - AutoCrafterMultiblockTier2Mirrored, AutoCrafterMultiblockTier3, - AutoCrafterMultiblockTier3Mirrored, - PumpkinCannonStarshipWeaponMultiblock, + HorizontalPumpkinCannonStarshipWeaponMultiblock, CthulhuBeamStarshipWeaponMultiblockBottom, CthulhuBeamStarshipWeaponMultiblockTop, CthulhuBeamStarshipWeaponMultiblockSide, FlamethrowerStarshipWeaponMultiblock, CapitalBeamStarshipWeaponMultiblock, - SkullThrowerStarshipWeaponMultiblock, - GazeStarshipWeaponMultiblock, PlanterMultiblockTier1, PlanterMultiblockTier2, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt index de0bf1ce4f..d8de21d911 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield import net.horizonsend.ion.server.features.multiblock.MultiblockShape -object AreaShield10 : AreaShield(radius = 10) { +object AreaShield10 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 10) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt index 9771a73b28..4be75a93ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield import net.horizonsend.ion.server.features.multiblock.MultiblockShape -object AreaShield20 : AreaShield(radius = 20) { +object AreaShield20 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 20) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt index 43dea169ed..a69d8bb9a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield import net.horizonsend.ion.server.features.multiblock.MultiblockShape -object AreaShield30 : AreaShield(radius = 30) { +object AreaShield30 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 30) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt index 225639687a..c205107121 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield import net.horizonsend.ion.server.features.multiblock.MultiblockShape -object AreaShield5 : AreaShield(radius = 5) { +object AreaShield5 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 5) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt index 094b30ca40..1d9b21a8a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt @@ -1,21 +1,21 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting +package net.horizonsend.ion.server.features.multiblock.crafting import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ConsumedItemIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.GasCanisterIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ProgressHolderItemIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ResourceIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.FurnaceMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.ProcessingMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.ItemResult -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.MultiRecipeResult -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.ProgressItemResult -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.SoundResult +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ConsumedItemIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.GasCanisterIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ProgressHolderItemIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.ProcessingMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiRecipeResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.SoundResult import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt index f0833fcfd1..d1792b70f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.type.crafting.recipe import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ItemConsumable -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ResourceIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.MultiblockRecipeResult +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemConsumable +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult import org.bukkit.block.Sign import org.bukkit.block.data.type.Furnace import org.bukkit.event.inventory.FurnaceBurnEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt index 98b89fe07e..bfdfb82a48 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt @@ -2,10 +2,10 @@ package net.horizonsend.ion.server.features.multiblock.type.crafting.recipe import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ItemConsumable -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ResourceIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.MultiblockRecipeResult +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemConsumable +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt index 04e8e78b56..379b761939 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.crafting.result -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt index 4869c576a5..cba7730ba0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.crafting.result import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign import org.bukkit.inventory.CraftingInventory import org.bukkit.inventory.FurnaceInventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiRecipeResult.kt index 16009a85b6..46241f3860 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiRecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiRecipeResult.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiblockRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiblockRecipeResult.kt index 48e3729215..ce5d9ed5ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiblockRecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiblockRecipeResult.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt index 005bf97094..ba8e0681a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.crafting.result import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.ProgressHolder -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ResourceResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ResourceResult.kt index 9ecc24f0e3..9b1f9cd82e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ResourceResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ResourceResult.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/SoundResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/SoundResult.kt index 04d2f80a1a..d505724620 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/SoundResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/SoundResult.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.Registry import org.bukkit.Sound import org.bukkit.SoundCategory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt index 8d9306ad93..d16a39cd5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt @@ -1,10 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.industry - import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock - import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt index 944bb5e038..f4bd386e83 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt @@ -1,10 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.type.industry - +package net.horizonsend.ion.server.features.multiblock.industry import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock - import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace import org.bukkit.block.Sign From d1f92d51e867661b9048c7de2f0c03b1e9e4cf40 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 14 Feb 2024 15:01:14 -0600 Subject: [PATCH 002/500] organization --- .../ion/server/command/starship/MiscStarshipCommands.kt | 1 + .../ion/server/features/ai/spawning/AISpawningUtils.kt | 1 + .../net/horizonsend/ion/server/features/chat/ChatChannel.kt | 1 + .../net/horizonsend/ion/server/features/npcs/StarshipDealers.kt | 1 + 4 files changed, 4 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index f2395490d0..9cf1463c42 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -41,6 +41,7 @@ import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.Na import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand +import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.AutoTurretTargeting import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt index df610429ea..b4cc915e7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.ai.configuration.AITemplate import net.horizonsend.ion.server.features.ai.module.misc.GlowModule import net.horizonsend.ion.server.features.ai.starship.StarshipTemplate +import net.horizonsend.ion.server.configuration.AISpawningConfiguration import net.horizonsend.ion.server.features.npcs.StarshipDealers import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt index b1baee4fac..2347fdacaa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt @@ -29,6 +29,7 @@ import net.horizonsend.ion.server.features.sidebar.SidebarIcon import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.control.controllers.player.PlayerController +import net.horizonsend.ion.server.miscellaneous.utils.CommonPlayerWrapper.Companion.common import net.horizonsend.ion.server.features.starship.fleet.Fleets import net.horizonsend.ion.server.miscellaneous.utils.CommonPlayerWrapper.Companion.common import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt index 226899d9e8..968ade164f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.configuration.ServerConfiguration import net.horizonsend.ion.server.features.npcs.traits.ShipDealerTrait import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.progression.Levels +import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement import net.horizonsend.ion.server.miscellaneous.utils.MenuHelper From 6d940c3f572fe26a8764acdc5c4a08cd42841389 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 24 Apr 2024 13:17:21 -0500 Subject: [PATCH 003/500] delete old space world system --- .../ion/server/command/starship/MiscStarshipCommands.kt | 1 - .../ion/server/features/ai/spawning/AISpawningUtils.kt | 1 - .../net/horizonsend/ion/server/features/chat/ChatChannel.kt | 1 - 3 files changed, 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index 9cf1463c42..f2395490d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -41,7 +41,6 @@ import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.Na import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand -import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.AutoTurretTargeting import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt index b4cc915e7c..df610429ea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.ai.configuration.AITemplate import net.horizonsend.ion.server.features.ai.module.misc.GlowModule import net.horizonsend.ion.server.features.ai.starship.StarshipTemplate -import net.horizonsend.ion.server.configuration.AISpawningConfiguration import net.horizonsend.ion.server.features.npcs.StarshipDealers import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt index 2347fdacaa..b1baee4fac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/ChatChannel.kt @@ -29,7 +29,6 @@ import net.horizonsend.ion.server.features.sidebar.SidebarIcon import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.control.controllers.player.PlayerController -import net.horizonsend.ion.server.miscellaneous.utils.CommonPlayerWrapper.Companion.common import net.horizonsend.ion.server.features.starship.fleet.Fleets import net.horizonsend.ion.server.miscellaneous.utils.CommonPlayerWrapper.Companion.common import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId From ec3b49906ef6943eb67bd8658e3d313605b85288 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Mar 2024 13:52:07 -0600 Subject: [PATCH 004/500] some async multiblock frameworks, start of multiblock entities, refactors --- .../server/command/misc/MultiblockCommand.kt | 6 +- .../features/multiblock/BlockRequirement.kt | 15 ++ .../features/multiblock/MultiblockEntity.kt | 28 +++- .../features/multiblock/MultiblockShape.kt | 154 +++++++++++++----- .../server/features/multiblock/Multiblocks.kt | 8 +- .../multiblock/util/AsyncBlockUtils.kt | 38 +++++ .../features/multiblock/util/AsyncTick.kt | 25 --- .../features/multiblock/util/BlockSnapshot.kt | 3 + 8 files changed, 201 insertions(+), 76 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncTick.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 165057140b..27836007df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -50,8 +50,8 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { val face = sign.getFacing().oppositeFace - lastMatch.shape.getRequirementMap(face).forEach { (coords, requirementMap) -> - val (expected, requirement) = requirementMap + lastMatch.shape.getRequirementMap(face).forEach { (coords, requirement) -> + val expected = requirement.example val requirementX = coords.x val requirementY = coords.y @@ -88,7 +88,7 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { val (x, y, z) = absolute - val blockData = requirement.first + val blockData = requirement.example val existingBlock = sender.world.getBlockAt(x, y, z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt new file mode 100644 index 0000000000..a2a025ad71 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.multiblock + +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData + +class BlockRequirement( + val example: BlockData, + private val check: (Block, BlockFace, Boolean) -> Boolean, + private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean +) { + operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = check.invoke(block, inward, loadChunks) + + suspend fun checkAsync(block: Block, inward: BlockFace, loadChunks: Boolean) = asyncCheck.invoke(block, inward, loadChunks) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt index 8089a6b921..9c01188e5c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt @@ -5,25 +5,47 @@ import org.bukkit.Location import org.bukkit.World /** - * * @param x The absolute x position of this multiblock's origin location * @param y The absolute x position of this multiblock's origin location * @param z The absolute x position of this multiblock's origin location + * + * @param world The world this multiblock is in + * + * @param type The type of multiblock this entity represents **/ abstract class MultiblockEntity( val x: Int, val y: Int, val z: Int, val world: World, - val multiblock: Multiblock + val type: Multiblock ) { + /** + * Returns the origin of this multiblock as a Location + **/ val location get() = Location(world, x.toDouble(), y.toDouble(), z.toDouble()) + /** + * Returns the origin of this multiblock as a Vec3i + **/ val vec3i get() = Vec3i(x, y, z) + /** + * Stores any additional data for this multiblock (e.g. power, owner, etc) + **/ abstract fun storeAdditionalData(store: PersistentMultiblockData) + /** + * Returns the serializable data for this multiblock entity + * + * Additional data is stored via `storeAdditionalData` + * + * This data is serialized and stored on the chunk when not loaded. + **/ fun store(): PersistentMultiblockData { - return PersistentMultiblockData(x, y, z, multiblock) + val store = PersistentMultiblockData(x, y, z, type) + storeAdditionalData(store) + + return store } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt index 62231625c0..7eb23f32ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt @@ -2,6 +2,9 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.multiblock.util.awaitAllValues +import net.horizonsend.ion.server.features.multiblock.util.getBlockAsync +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BARGE_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE @@ -42,21 +45,20 @@ import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.minecraft.world.level.block.AbstractFurnaceBlock import org.bukkit.Material import org.bukkit.Particle +import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.Furnace import org.bukkit.block.data.type.Slab import java.util.EnumSet import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.set -/** Parameters: block, inward, load chunks */ -private typealias BlockRequirement = (Block, BlockFace, Boolean) -> Boolean - class MultiblockShape { // Cache of direction to requirement, so it doesn't need to be calculated every time based on the direction - private val requirements = mutableMapOf>>() + private val requirements = mutableMapOf>() var signCentered = false private var ignoreDirection = false // ignore whether inward direction matches @@ -168,7 +170,7 @@ class MultiblockShape { } } - fun getRequirementMap(inwardFace: BlockFace): MutableMap> { + fun getRequirementMap(inwardFace: BlockFace): MutableMap { return requirements.getOrPut(inwardFace) { require(CARDINAL_BLOCK_FACES.contains(inwardFace)) { "Unsupported inward direction: $inwardFace" } return@getOrPut mutableMapOf() @@ -190,8 +192,7 @@ class MultiblockShape { } fun checkRequirementsSpecific(origin: Block, face: BlockFace, loadChunks: Boolean, particles: Boolean): Boolean { - return getRequirementMap(face).all { (offset, requirementMap) -> - val (_, requirement) = requirementMap + return getRequirementMap(face).all { (offset, requirement) -> val x = offset.x val y = offset.y val z = offset.z @@ -212,9 +213,29 @@ class MultiblockShape { } } + /** + * + * TODO + **/ + suspend fun checkRequirementsAsync(world: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { + val (originX, originY, originZ) = origin + + val blocks = getRequirementMap(inward).map { (offset, _) -> + val (x, y, z) = offset + + offset to getBlockAsync(world, originX + x, originY + y, originZ + z) + }.toMap().awaitAllValues() + + return getRequirementMap(inward).all { (offset, requirement) -> + val block = blocks[offset]!! + + requirement.checkAsync(block, inward, loadChunks) + } + } + private val allLocations = mutableSetOf() // used for checking for duplicates - private fun addRequirement(right: Int, upward: Int, inward: Int, type: BlockData, requirement: BlockRequirement) { + private fun addRequirement(right: Int, upward: Int, inward: Int, requirement: BlockRequirement) { if (!allLocations.add(Vec3i(right, upward, inward))) { Exception("Multiblock ${javaClass.simpleName} has more than one block at $right, $upward, $inward!").printStackTrace() } @@ -226,27 +247,56 @@ class MultiblockShape { val intTrio = Vec3i(x, upward, z) val requirementMap = getRequirementMap(inwardFace) - requirementMap[intTrio] = type to requirement + requirementMap[intTrio] = requirement } } @Suppress("unused") class RequirementBuilder(val shape: MultiblockShape, val right: Int, val upward: Int, val inward: Int) { - private fun complete(type: BlockData, requirement: BlockRequirement) = shape.addRequirement(right, upward, inward, type, requirement) + private fun complete(requirement: BlockRequirement) = shape.addRequirement(right, upward, inward, requirement) fun type(type: Material) { - complete(type.createBlockData()) { block, _, _ -> block.getTypeSafe() == type } + val requirement = BlockRequirement( + example = type.createBlockData(), + check = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, + asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type } + ) + + complete(requirement) } fun anyType(vararg types: Material) { val typeSet = EnumSet.copyOf(types.toList()) - complete(types.first().createBlockData()) { block, _, loadChunks -> - typeSet.contains(if (loadChunks) block.type else block.getTypeSafe()) - } + + val requirement = BlockRequirement( + example = types.first().createBlockData(), + check = { block, _, loadChunks -> + typeSet.contains(if (loadChunks) block.type else block.getTypeSafe()) + }, + asyncCheck = { block, _, loadChunks -> + val type = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type + + typeSet.contains(type) + } + ) + + complete(requirement) } fun customBlock(customBlock: CustomBlock) { - complete(customBlock.blockData) { block, _, _ -> CustomBlocks.getByBlock(block) === customBlock } + val requirement = BlockRequirement( + example = customBlock.blockData, + check = { block, _, loadChunks -> + if (loadChunks) CustomBlocks.getByBlock(block) else { + getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } + } === customBlock + }, + asyncCheck = { block, _, loadChunks -> + getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.let { CustomBlocks.getByBlockData(it.data) } === customBlock + } + ) + + complete(requirement) } fun anyType(types: Iterable) = anyType(*types.toList().toTypedArray()) @@ -280,26 +330,41 @@ class MultiblockShape { fun anySlab() = filteredTypes { it.isSlab } fun anyDoubleSlab() = complete( - Material.STONE_BRICK_SLAB.createBlockData().apply { - this as Slab - this.type = Slab.Type.DOUBLE - } - ) { block, _, loadChunks -> - val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) - return@complete blockData is Slab && blockData.type == Slab.Type.DOUBLE - } + BlockRequirement( + example = Material.STONE_BRICK_SLAB.createBlockData().apply { + this as Slab + this.type = Slab.Type.DOUBLE + }, + check = { block, _, loadChunks -> + val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) + blockData is Slab && blockData.type == Slab.Type.DOUBLE + }, + asyncCheck = { block, _, loadChunks -> + val blockData: BlockData? = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.data + blockData is Slab && blockData.type == Slab.Type.DOUBLE + } + ) + ) fun anySlabOrStairs() = filteredTypes { it.isSlab || it.isStairs } + fun terracottaOrDoubleslab() { - complete( - Material.TERRACOTTA.createBlockData() - ) { block, _, loadChunks -> - val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) - val blockType = if (loadChunks) block.type else block.getTypeSafe() - - return@complete (blockData is Slab && blockData.type == Slab.Type.DOUBLE) - || TERRACOTTA_TYPES.contains(blockType) - } + BlockRequirement( + example = Material.TERRACOTTA.createBlockData(), + check = { block, _, loadChunks -> + val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) + val blockType = if (loadChunks) block.type else block.getTypeSafe() + + (blockData is Slab && blockData.type == Slab.Type.DOUBLE) || TERRACOTTA_TYPES.contains(blockType) + }, + asyncCheck = { block, _, loadChunks -> + val blockSnapshot = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks) + val blockData = blockSnapshot?.data + val blockType = blockSnapshot?.type + + (blockData is Slab && blockData.type == Slab.Type.DOUBLE) || TERRACOTTA_TYPES.contains(blockType) + } + ) } fun concrete() = filteredTypes { it.isConcrete } @@ -381,14 +446,23 @@ class MultiblockShape { fun lightningRod() = type(Material.LIGHTNING_ROD) - fun machineFurnace() = complete(Material.FURNACE.createBlockData()) { block, inward, loadChunks -> - val blockData = if (loadChunks) block.getNMSBlockData() else - getNMSBlockSateSafe(block.world, block.x, block.y, block.z) ?: return@complete false - - if (blockData.bukkitMaterial != Material.FURNACE) return@complete false - val facing = blockData.getValue(AbstractFurnaceBlock.FACING).blockFace - return@complete facing == inward.oppositeFace - } + fun machineFurnace() = complete(BlockRequirement( + example = Material.FURNACE.createBlockData(), + check = check@{ block, inward, loadChunks -> + val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockDataSafe(block.world, block.x, block.y, block.z) ?: return@check false + + if (blockData.bukkitMaterial != Material.FURNACE) return@check false + val facing = blockData.getValue(AbstractFurnaceBlock.FACING).blockFace + return@check facing == inward.oppositeFace + }, + asyncCheck = asyncCheck@{ block, inward, loadChunks -> + val blockData = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.data as? Furnace ?: return@asyncCheck false + + if (blockData.material != Material.FURNACE) return@asyncCheck false + val facing = blockData.facing + return@asyncCheck facing == inward.oppositeFace + } + )) fun solidBlock() = anyType( Material.STONE_BRICKS, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index ea8eb737b6..65ab1e1cc3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.achievements.Achievement import net.horizonsend.ion.server.features.achievements.rewardAchievement @@ -141,7 +142,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent -import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN import net.kyori.adventure.text.format.TextDecoration import org.bukkit.Location import org.bukkit.block.Sign @@ -453,10 +454,7 @@ object Multiblocks : IonServerComponent() { val command = "/multiblock check $tierName ${sign.x} ${sign.y} ${sign.z}" - val tierText = text().color(NamedTextColor.GRAY) - .append(text("[")) - .append(text(tierName).color(NamedTextColor.DARK_GREEN).decorate(TextDecoration.BOLD)) - .append(text("]")) + val tierText = bracketed(text(tierName, DARK_GREEN, TextDecoration.BOLD)) .clickEvent(ClickEvent.runCommand(command)) .hoverEvent(text(command).asHoverEvent()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt new file mode 100644 index 0000000000..dca995a54a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -0,0 +1,38 @@ +package net.horizonsend.ion.server.features.multiblock.util + +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.future.asDeferred +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded +import org.bukkit.ChunkSnapshot +import org.bukkit.World +import org.bukkit.block.Block + +suspend fun getChunkSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): ChunkSnapshot? { + val chunk = if (loadChunks) { + world.getChunkAtAsync(x shr 4, z shr 4).asDeferred().await() + } else { + world.getChunkAtIfLoaded(x shr 4, z shr 4) ?: return null + } + + return chunk.chunkSnapshot +} + +/** Retrieves a snapshot of an async block */ +suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): BlockSnapshot? { + return getChunkSnapshotAsync(world, x, y, z, loadChunks)?.getBlockSnapshot(x, y, z) +} + +fun getBlockAsync(world: World, x: Int, y: Int, z: Int): Deferred { + val deferred = CompletableDeferred() + + Tasks.async { + deferred.complete(world.getBlockAt(x, y, z)) + } + + return deferred +} + +suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncTick.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncTick.kt deleted file mode 100644 index ddd4f3542e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncTick.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.util - -import kotlinx.coroutines.future.asDeferred -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot -import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded -import org.bukkit.ChunkSnapshot -import org.bukkit.World - -object AsyncTick { - suspend fun getChunkSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): ChunkSnapshot? { - val chunk = if (loadChunks) { - world.getChunkAtAsync(x shr 4, z shr 4).asDeferred().await() - } else { - world.getChunkAtIfLoaded(x shr 4, z shr 4) ?: return null - } - - return chunk.chunkSnapshot - } - - /** Retrieves a snapshot of an async block */ - suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): BlockSnapshot? { - return getChunkSnapshotAsync(world, x, y, z)?.getBlockSnapshot(x, y, z) - } - -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt index fe75ab244b..6113954fce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.util import org.bukkit.ChunkSnapshot import org.bukkit.Material +import org.bukkit.block.Block import org.bukkit.block.data.BlockData class BlockSnapshot(val x: Int, val y: Int, val z: Int, val type: Material, val data: BlockData) { @@ -15,5 +16,7 @@ class BlockSnapshot(val x: Int, val y: Int, val z: Int, val type: Material, val return BlockSnapshot(x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) } + + fun Block.snapshot(): BlockSnapshot = BlockSnapshot(x, y, z, type, blockData) } } From 2864b098764f16df622caee3d89dffc26099afc3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 4 Mar 2024 22:56:51 -0600 Subject: [PATCH 005/500] get async bukkit blockstate access working --- .../server/command/misc/MultiblockCommand.kt | 3 +- .../features/multiblock/BlockRequirement.kt | 8 +- .../server/features/multiblock/Multiblock.kt | 40 ++++++++- .../features/multiblock/MultiblockShape.kt | 39 ++++++--- .../server/features/multiblock/Multiblocks.kt | 69 ++++++++++----- .../multiblock/util/AsyncBlockUtils.kt | 87 ++++++++++++++++++- 6 files changed, 205 insertions(+), 41 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 27836007df..f9e5173caa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -45,8 +45,7 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { @CommandCompletion("@multiblocks") @CommandPermission("ion.multiblock.check") fun onCheck(sender: Player, lastMatch: Multiblock, x: Int, y: Int, z: Int) { - val sign = sender.world.getBlockAt(x, y, z).state as? Sign - ?: return sender.userError("Block at $x $y $z isn't a sign!") + val sign = sender.world.getBlockAt(x, y, z).state as? Sign ?: return sender.userError("Block at $x $y $z isn't a sign!") val face = sign.getFacing().oppositeFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt index a2a025ad71..2bee8808a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt @@ -5,11 +5,17 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData class BlockRequirement( - val example: BlockData, + var example: BlockData, private val check: (Block, BlockFace, Boolean) -> Boolean, private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean ) { operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = check.invoke(block, inward, loadChunks) suspend fun checkAsync(block: Block, inward: BlockFace, loadChunks: Boolean) = asyncCheck.invoke(block, inward, loadChunks) + + fun setExample(blockData: BlockData): BlockRequirement { + this.example = blockData + + return this + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 95ac7ebf9b..0d4f09204e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.multiblock +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isValidYLevel @@ -7,10 +9,11 @@ import net.kyori.adventure.text.Component import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import org.bukkit.Location +import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.block.sign.Side +import org.bukkit.block.data.BlockData import org.bukkit.entity.Player abstract class Multiblock { @@ -65,13 +68,42 @@ abstract class Multiblock { originBlock: Block, inward: BlockFace, loadChunks: Boolean = true, - particles: Boolean = false + particles: Boolean = false, ): Boolean { return shape.checkRequirements(originBlock, inward, loadChunks, particles) } + suspend fun signMatchesStructureAsync( + signLocation: Location, + inward: BlockFace, + loadChunks: Boolean = true + ): Boolean { + val world = signLocation.world + + val x = signLocation.blockX + inward.modX + val y = signLocation.blockY + inward.modY + val z = signLocation.blockZ + inward.modZ + + if (!isValidYLevel(y)) return false + + val blockData: BlockData? = getBlockSnapshotAsync(world, x, y, z, loadChunks)?.data + + if (blockData !is org.bukkit.block.data.type.Sign) return false + + return blockMatchesStructureAsync(world, Vec3i(x, y, z), inward, loadChunks) + } + + suspend fun blockMatchesStructureAsync( + originWorld: World, + origin: Vec3i, + inward: BlockFace, + loadChunks: Boolean = true + ): Boolean { + return shape.checkRequirementsAsync(originWorld, origin, inward, loadChunks) + } + open fun matchesUndetectedSign(sign: Sign): Boolean { - return (sign.getSide(Side.FRONT).line(0) as TextComponent).content().equals("[$name]", ignoreCase = true) + return (sign.line(0) as TextComponent).content().equals("[$name]", ignoreCase = true) } open fun setupSign(player: Player, sign: Sign) { @@ -80,7 +112,7 @@ abstract class Multiblock { for (i in 0..3) { val text = signText[i] if (text != null) { - sign.getSide(Side.FRONT).line(i, text) + sign.line(i, text) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt index 7eb23f32ff..ce0259dced 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt @@ -96,9 +96,7 @@ class MultiblockShape { ) /** - * This is used for structuring it by y, z, x. See the area shield multiblocks for an example. - * - * @sample net.horizonsend.ion.server.features.multiblock.areashield.AreaShield10.buildStructure + * This is used for structuring it by y, z, x. See the area shield multiblocks for an example */ fun z(z: Int, block: Z.() -> Unit) = Z( this, @@ -214,10 +212,29 @@ class MultiblockShape { } /** + * Checks all possible directions a multiblock face + * + * + **/ + suspend fun checkRequirementsAsync(originWorld: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { + val realOrigin = if (signCentered) origin + Vec3i(inward.oppositeFace.modX, 0, inward.oppositeFace.modZ) else origin + + // check all directions if ignoring direction + for (face in if (ignoreDirection) CARDINAL_BLOCK_FACES else listOf(inward)) { + if (checkRequirementsSpecificAsync(originWorld, realOrigin, face, loadChunks)) { + return true + } + } + + return false + } + + /** + * Checks a single direction of the multiblock * - * TODO + * TODO more documentation **/ - suspend fun checkRequirementsAsync(world: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { + suspend fun checkRequirementsSpecificAsync(world: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { val (originX, originY, originZ) = origin val blocks = getRequirementMap(inward).map { (offset, _) -> @@ -265,7 +282,7 @@ class MultiblockShape { complete(requirement) } - fun anyType(vararg types: Material) { + fun anyType(vararg types: Material, edit: BlockRequirement.() -> Unit = {}) { val typeSet = EnumSet.copyOf(types.toList()) val requirement = BlockRequirement( @@ -281,6 +298,8 @@ class MultiblockShape { ) complete(requirement) + + edit(requirement) } fun customBlock(customBlock: CustomBlock) { @@ -299,14 +318,14 @@ class MultiblockShape { complete(requirement) } - fun anyType(types: Iterable) = anyType(*types.toList().toTypedArray()) + fun anyType(types: Iterable, edit: BlockRequirement.() -> Unit = {}) = anyType(*types.toList().toTypedArray(), edit = edit) fun filteredTypes(filter: (Material) -> Boolean) = anyType(MATERIALS.filter(filter)) - fun carbyne() = anyType(CONCRETE_TYPES) + fun carbyne() = anyType(CONCRETE_TYPES) { setExample(Material.GRAY_CONCRETE.createBlockData()) } - fun terracotta() = anyType(TERRACOTTA_TYPES) - fun stainedTerracotta() = anyType(STAINED_TERRACOTTA_TYPES) + fun terracotta() = anyType(TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } + fun stainedTerracotta() = anyType(STAINED_TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } fun glass() = type(Material.GLASS) fun anvil() = type(Material.ANVIL) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 65ab1e1cc3..e56b8dc2a0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -1,6 +1,10 @@ package net.horizonsend.ion.server.features.multiblock import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.server.IonServerComponent @@ -136,9 +140,10 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopLightTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopQuadTurretMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopTriTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretBaseMultiblock +import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent @@ -261,7 +266,6 @@ object Multiblocks : IonServerComponent() { BottomIonTurretMultiblock, TopQuadTurretMultiblock, BottomQuadTurretMultiblock, - TurretBaseMultiblock, HorizontalRocketStarshipWeaponMultiblock, UpwardRocketStarshipWeaponMultiblock, DownwardRocketStarshipWeaponMultiblock, @@ -320,6 +324,8 @@ object Multiblocks : IonServerComponent() { ) } + val context = CoroutineScope(Dispatchers.Default + SupervisorJob()) + private val multiblockCache: MutableMap = Object2ObjectOpenHashMap() override fun onEnable() { @@ -392,50 +398,70 @@ object Multiblocks : IonServerComponent() { return sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) == multiblock::class.simpleName } + /** + * The check for when someone right-clicks an undetected multiblock + **/ @EventHandler(priority = EventPriority.HIGHEST) - fun onInteractMultiblockSign(event: PlayerInteractEvent) { + fun onInteractMultiblockSign(event: PlayerInteractEvent) = context.launch { if (event.hand != EquipmentSlot.HAND || event.action != Action.RIGHT_CLICK_BLOCK) { - return + return@launch } - val sign = event.clickedBlock?.state as? Sign ?: return + val clickedBlock = event.clickedBlock ?: return@launch + + val sign = getBukkitBlockState(clickedBlock, false) as? Sign ?: return@launch + + // Don't bother checking detected multiblocks + if (sign.persistentDataContainer.has(NamespacedKeys.MULTIBLOCK)) return@launch + var lastMatch: Multiblock? = null val player = event.player if (!player.hasPermission("starlegacy.multiblock.detect")) { player.userError("You don't have permission to detect multiblocks!") - return + return@launch } + // Check all multiblocks for (multiblock in multiblocks) { + // If it has the same sign text as the multiblock if (multiblock.matchesUndetectedSign(sign)) { + // And is built properly if (multiblock.signMatchesStructure(sign, particles = true)) { + // Check permissions here because different tiers might have the same text multiblock.requiredPermission?.let { - if (!player.hasPermission(it)) return player.userError("You don't have permission to use that multiblock!") + if (!player.hasPermission(it)) player.userError("You don't have permission to use that multiblock!") + return@launch } - event.player.rewardAchievement(Achievement.DETECT_MULTIBLOCK) + // Update everything that needs to be done sync + Tasks.sync { + event.player.rewardAchievement(Achievement.DETECT_MULTIBLOCK) - multiblock.setupSign(player, sign) - sign.persistentDataContainer.set( - NamespacedKeys.MULTIBLOCK, - PersistentDataType.STRING, - multiblock::class.simpleName!! - ) - sign.isWaxed = true - sign.update() - return + multiblock.setupSign(player, sign) + + sign.persistentDataContainer.set( + NamespacedKeys.MULTIBLOCK, + PersistentDataType.STRING, + multiblock::class.simpleName!! // Shouldn't be any anonymous multiblocks + ) + + sign.isWaxed = true + sign.update() + } + + return@launch } else { + // Store the multi that last matched sign text lastMatch = multiblock } } } if (lastMatch != null) { - player.userError( - "Improperly built ${lastMatch.name}. Make sure every block is correctly placed!" - ) + player.userError("Improperly built ${lastMatch.name}. Make sure every block is correctly placed!") + // Prompt the help command setupCommand(player, sign, lastMatch) } } @@ -458,9 +484,8 @@ object Multiblocks : IonServerComponent() { .clickEvent(ClickEvent.runCommand(command)) .hoverEvent(text(command).asHoverEvent()) - if (possibleTiers.indexOf(tier) != possibleTiers.size - 1) tierText.append(text(", ")) - message.append(tierText) + if (possibleTiers.indexOf(tier) != possibleTiers.size - 1) message.append(text(", ")) } player.sendMessage(message.build()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index dca995a54a..e7ca52d94d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -1,16 +1,34 @@ package net.horizonsend.ion.server.features.multiblock.util +import net.minecraft.world.level.block.state.BlockState as NMSBlockState +import org.bukkit.block.BlockState as BukkitBlockState import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred import kotlinx.coroutines.future.asDeferred import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.loadChunkAsync +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.core.BlockPos +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.chunk.LevelChunk import org.bukkit.ChunkSnapshot +import org.bukkit.Material import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.data.BlockData +import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock +import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockState +import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockStates +import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData +import org.bukkit.craftbukkit.v1_19_R3.util.CraftMagicNumbers -suspend fun getChunkSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): ChunkSnapshot? { +/** + * X and Z in real coordinates + **/ +suspend fun getChunkSnapshotAsync(world: World, x: Int, z: Int, loadChunks: Boolean = false): ChunkSnapshot? { val chunk = if (loadChunks) { world.getChunkAtAsync(x shr 4, z shr 4).asDeferred().await() } else { @@ -22,7 +40,7 @@ suspend fun getChunkSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChun /** Retrieves a snapshot of an async block */ suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): BlockSnapshot? { - return getChunkSnapshotAsync(world, x, y, z, loadChunks)?.getBlockSnapshot(x, y, z) + return getChunkSnapshotAsync(world, x, z, loadChunks)?.getBlockSnapshot(x, y, z) } fun getBlockAsync(world: World, x: Int, y: Int, z: Int): Deferred { @@ -36,3 +54,68 @@ fun getBlockAsync(world: World, x: Int, y: Int, z: Int): Deferred { } suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } + +suspend fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { + val serverLevel: ServerLevel = block.world.minecraft + val blockPos = (block as CraftBlock).position + + if (serverLevel.isOutsideBuildHeight(blockPos)) { + return null + } + + val chunkX = block.x.shr(4) + val chunkZ = block.z.shr(4) + + if (serverLevel.isLoaded(blockPos)) { + return serverLevel.getChunk(chunkX, chunkZ).getBlockEntity(blockPos, LevelChunk.EntityCreationType.IMMEDIATE) + } + + if (!loadChunks) { + return null + } + + val entity = CompletableDeferred() + + loadChunkAsync(block.world, chunkX, chunkZ) { + entity.complete(it.minecraft.getBlockEntity(blockPos)) + } + + return entity.await() +} + +@Suppress("UNCHECKED_CAST") +suspend fun getAndCastNMSTileEntity(block: Block, loadChunks: Boolean): T? = getNMSTileEntity(block, loadChunks) as? T + +suspend fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlockState? { + val world = block.world + val blockPos = (block as CraftBlock).position + val data = getBlockSnapshotAsync(world, blockPos.x, blockPos.y, blockPos.z, loadChunks)?.data ?: return null + + val tileEntity = getNMSTileEntity(block, loadChunks) + + val blockState = createBlockState(world, blockPos, data, tileEntity) + blockState.worldHandle = world.minecraft + + return blockState +} + +fun createBlockState(world: World, blockPos: BlockPos, data: BlockData, tileEntity: BlockEntity?): CraftBlockState { + val getFactoryForMaterial = CraftBlockStates::class.java.getDeclaredMethod("getFactory", Material::class.java) + getFactoryForMaterial.isAccessible = true + + val material = CraftMagicNumbers.getMaterial((data as CraftBlockData).state.block) + + val factory = getFactoryForMaterial.invoke(null, material) + + val method = factory::class.java.getDeclaredMethod( + "createBlockState", + World::class.javaObjectType, + BlockPos::class.javaObjectType, + NMSBlockState::class.javaObjectType, + BlockEntity::class.javaObjectType + ) + + method.isAccessible = true + + return method.invoke(factory, world, blockPos, data.state, tileEntity) as CraftBlockState +} From 110a318cfb7f63d0808ce9cf8136f6b9963a963c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 4 Mar 2024 23:11:12 -0600 Subject: [PATCH 006/500] fix imports --- .../net/starlegacy/javautil/SignUtils.java | 2 +- .../server/command/misc/RegenerateCommand.kt | 2 +- .../command/starship/MiscStarshipCommands.kt | 2 +- .../custom/items/type/tool/CratePlacer.kt | 2 + .../custom/items/util/StoredValues.kt | 2 +- .../server/features/machine/PowerMachines.kt | 26 +--- .../features/multiblock/MultiblockEntity.kt | 10 ++ .../features/multiblock/MultiblockShape.kt | 2 +- .../server/features/multiblock/Multiblocks.kt | 15 +- .../multiblock/PersistentMultiblockData.kt | 12 +- .../type/ammo/MissileLoaderMultiblock.kt | 2 +- .../type/crafting/MultiblockRecipes.kt | 2 +- .../ConnectedDockingTubeMultiblock.kt | 2 +- .../DisconnectedDockingTubeMultiblock.kt | 2 +- .../type/dockingtube/StoredButtonDataType.kt | 2 +- .../multiblock/type/drills/DrillMultiblock.kt | 2 +- .../type/industry/PlatePressMultiblock.kt | 2 +- .../type/misc/ItemSplitterMultiblock.kt | 2 +- .../type/misc/OdometerMultiblock.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 71 +++++++++ .../type/starshipweapon/EntityMultiblock.kt | 26 ++++ .../multiblock/util/AsyncBlockUtils.kt | 10 +- .../features/ores/generation/OreGeneration.kt | 4 +- .../server/features/ores/storage/OreData.kt | 2 +- .../server/features/space/data/BlockData.kt | 4 +- .../features/space/data/CompletedSection.kt | 6 +- .../features/space/data/StoredChunkBlocks.kt | 2 +- .../space/encounters/BridgeOfDeath.kt | 4 +- .../features/space/encounters/CoolantLeak.kt | 10 +- .../features/space/encounters/CowTipper.kt | 6 +- .../features/space/encounters/DefenseBots.kt | 4 +- .../space/encounters/DefenseMatrix.kt | 2 +- .../features/space/encounters/DefuseBomb.kt | 4 +- .../features/space/encounters/Encounters.kt | 4 +- .../features/space/encounters/Infested.kt | 4 +- .../features/space/encounters/Passcode.kt | 6 +- .../space/encounters/SecondaryChest.kt | 4 +- .../features/space/encounters/TimedBomb.kt | 4 +- .../starship/active/SubsystemDetector.kt | 2 +- .../subsystem/misc/OdometerSubsystem.kt | 2 +- .../ion/server/features/world/IonChunk.kt | 136 ++++++++++++++++++ .../ion/server/features/world/IonWorld.kt | 67 ++++++++- .../environment/mobs/CustomMobSpawner.kt | 2 +- .../world/generation/generationUtils.kt | 2 +- .../generators/space/GenerateWreck.kt | 6 +- .../generators/space/SpaceGenerator.kt | 2 +- .../server/listener/fixers/BiomeFixer9001.kt | 2 +- .../server/listener/fixers/EdenFixer9000.kt | 2 +- .../miscellaneous/registrations/Listeners.kt | 3 + .../{ => persistence}/NamespacedKeys.kt | 4 +- .../persistence/StoredPosition.kt | 37 +++++ 51 files changed, 435 insertions(+), 102 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt rename server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/{ => persistence}/NamespacedKeys.kt (94%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt diff --git a/server/src/main/java/net/starlegacy/javautil/SignUtils.java b/server/src/main/java/net/starlegacy/javautil/SignUtils.java index 8ad5e5cd2a..afc9355fee 100644 --- a/server/src/main/java/net/starlegacy/javautil/SignUtils.java +++ b/server/src/main/java/net/starlegacy/javautil/SignUtils.java @@ -2,7 +2,7 @@ import net.horizonsend.ion.server.IonServer; import net.horizonsend.ion.server.features.machine.PowerMachines; -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys; +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.nbt.CompoundTag; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt index 860f60c295..0e57d71ca8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt @@ -22,7 +22,7 @@ import net.horizonsend.ion.server.features.ores.storage.Ore import net.horizonsend.ion.server.features.ores.storage.OreData import net.horizonsend.ion.server.features.space.data.BlockData import net.horizonsend.ion.server.features.space.data.CompletedSection -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getSelection diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index f2395490d0..3b45fa75e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -313,7 +313,7 @@ object MiscStarshipCommands : net.horizonsend.ion.server.command.SLCommand() { destinationWorld: World, maxRange: Int, sender: Player, - tier: Int?, + tier: Int? ) { val hyperdrive: HyperdriveSubsystem = tier?.let { Hyperspace.findHyperdrive(starship, tier) } ?: Hyperspace.findHyperdrive(starship) ?: fail { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/CratePlacer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/CratePlacer.kt index b0270b18b6..46843cb716 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/CratePlacer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/CratePlacer.kt @@ -10,6 +10,8 @@ import net.horizonsend.ion.server.features.custom.items.component.CustomItemComp import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.leftClickListener import net.horizonsend.ion.server.features.custom.items.component.PowerStorage import net.horizonsend.ion.server.features.custom.items.util.ItemFactory +import net.horizonsend.ion.server.features.economy.cargotrade.ShipmentManager.getShipmentItemId +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.horizonsend.ion.server.miscellaneous.utils.minecraft diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/StoredValues.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/StoredValues.kt index d238679e9f..752a7b10fb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/StoredValues.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/StoredValues.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.custom.items.util import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt index 52a9ea867e..72c64ee750 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt @@ -4,12 +4,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes -import net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient.ConsumedItemIngredient -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.FurnaceMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.MultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.ItemResult -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Bukkit @@ -61,25 +56,6 @@ object PowerMachines : IonServerComponent() { 0.0f, Int.MAX_VALUE )) - - addCopperRecipes(MultiblockRecipes.COPPER_OXIDATION) - addCopperRecipes(MultiblockRecipes.EXPOSED_COPPER_OXIDATION) - addCopperRecipes(MultiblockRecipes.WEATHERED_COPPER_OXIDATION) - } - } - - private fun addCopperRecipes(recipes : Set>) { - for (recipe in recipes) { - if (recipe !is FurnaceMultiblockRecipe) continue - val input = (recipe.smelting as ConsumedItemIngredient).ingredient - val output = (recipe.result as ItemResult).result - Bukkit.addRecipe(FurnaceRecipe( - NamespacedKey(IonServer, output.type.name.lowercase()), - output, - input.type, - 0.0f, - Int.MAX_VALUE - )) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt index 9c01188e5c..1128e7bb7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt @@ -48,4 +48,14 @@ abstract class MultiblockEntity( return store } + + /** + * Called upon world tick + **/ + fun tick() {} + + /** + * Called upon world tick. + **/ + fun tickAsync() {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt index ce0259dced..e595ab029c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt @@ -468,7 +468,7 @@ class MultiblockShape { fun machineFurnace() = complete(BlockRequirement( example = Material.FURNACE.createBlockData(), check = check@{ block, inward, loadChunks -> - val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockDataSafe(block.world, block.x, block.y, block.z) ?: return@check false + val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockSateSafe(block.world, block.x, block.y, block.z) ?: return@check false if (blockData.bukkitMaterial != Material.FURNACE) return@check false val facing = blockData.getValue(AbstractFurnaceBlock.FACING).blockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index e56b8dc2a0..9d2efb8609 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -81,6 +81,7 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblo import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic @@ -144,6 +145,8 @@ import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent @@ -320,7 +323,8 @@ object Multiblocks : IonServerComponent() { BattleCruiserReactorMultiblock, CruiserReactorMultiblock, BargeReactorMultiBlock, - OdometerMultiblock + OdometerMultiblock, + TestMultiblock ) } @@ -440,6 +444,15 @@ object Multiblocks : IonServerComponent() { multiblock.setupSign(player, sign) + val (x, y, z) = Vec3i(sign.location).minus(Vec3i(sign.getFacing().modX, 0, sign.getFacing().modZ)) + + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + val chunk = event.player.world.ion.getChunk(chunkX, chunkZ) ?: return@sync + + chunk.addMultiblock(multiblock, x, y, z) + sign.persistentDataContainer.set( NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt index e529ae6471..3b427feabf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.multiblock import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.ADDITIONAL_MULTIBLOCK_DATA -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.MULTIBLOCK -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.X -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.Y -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.Z +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ADDITIONAL_MULTIBLOCK_DATA +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z import org.bukkit.NamespacedKey import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry @@ -37,7 +37,7 @@ class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Mul pdc.set(Y, INTEGER, complex.y) pdc.set(Z, INTEGER, complex.z) - pdc.set(MULTIBLOCK, STRING, complex::class.java.simpleName) + pdc.set(MULTIBLOCK, STRING, complex.type::class.java.simpleName) pdc.set(ADDITIONAL_MULTIBLOCK_DATA, TAG_CONTAINER, complex.additionalData) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index 6eb6ed7b27..e29454587d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo +import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt index 1d9b21a8a6..2d32617fc0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt @@ -22,7 +22,7 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMu import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.getMatchingMaterials import org.bukkit.Material import org.bukkit.SoundCategory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt index f3356f1bf0..e7bf49c90c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.extensions.successActionMessage import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarships -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt index eb501e51e5..04209af053 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.extensions.successActionMessage import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarships -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/StoredButtonDataType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/StoredButtonDataType.kt index ad956bd270..b7313c1047 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/StoredButtonDataType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/StoredButtonDataType.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.dockingtube -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 991a0afab7..eb08524130 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -14,7 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultibloc import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.DRILL_USER +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DRILL_USER import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt index f4bd386e83..efe52f38db 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.industry +package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt index 66b6e500f3..57547e0abd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.SPLITTER_DIRECTION +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SPLITTER_DIRECTION import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getStateSafe diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt index af3e9838b9..4378bc7d7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.type.InteractableMultibloc import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.OdometerSubsystem -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt new file mode 100644 index 0000000000..d624b25262 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -0,0 +1,71 @@ +package net.horizonsend.ion.server.features.multiblock.type.misc + +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.plainText +import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.TextDecoration +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataType + +object TestMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { + override val name: String = "testmulti1" + + override val signText: Array = arrayOf( + Component.text("Removed for brevity", PIRATE_DARK_RED, TextDecoration.BOLD), + null, + null, + null + ) + + override fun MultiblockShape.buildStructure() { + at(0, 0,0 ).type(Material.BEDROCK) + } + + override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int): TestMultiblockEntity { + return TestMultiblockEntity(world, x, y, z, data.getAdditionalData(NamespacedKeys.key("test"), PersistentDataType.STRING) ?: "") + } + + class TestMultiblockEntity( + world: World, + x: Int, + y: Int, + z: Int, + var string: String + ) : MultiblockEntity(x, y, z, world, TestMultiblock) { + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.key("test"), PersistentDataType.STRING, string) + } + } + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + sign.line(2, player.inventory.itemInMainHand.displayName()) + + val origin = Vec3i(sign.location).minus(Vec3i(sign.getFacing().modX, 0, sign.getFacing().modZ)) + val (x, y, z) = origin + + val multi = getMultiblockEntity(sign.world, x, y, z) + + if (multi == null) { + player.userError("NO ENTITY! ORIGIN: $origin") + return + } + + multi.string = player.inventory.itemInMainHand.displayName().plainText() + + sign.update() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt new file mode 100644 index 0000000000..635f02fc08 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.multiblock.type.starshipweapon + +import net.horizonsend.ion.server.features.multiblock.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.PersistentMultiblockData +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import org.bukkit.World + +/** + * A multiblock which has a corresponding multiblock entity + * + * This interface provides methods for loading and saving the entity data into the chunk + **/ +interface EntityMultiblock { + /** + * Create the multiblock entity using the stored data + **/ + fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int): T + + fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): T? { + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + @Suppress("UNCHECKED_CAST") + return world.ion.getChunk(chunkX, chunkZ)?.getMultiblockEntity(x, y, z) as T? + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index e7ca52d94d..e4b4aea6de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -19,11 +19,11 @@ import org.bukkit.Material import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.data.BlockData -import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock -import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockState -import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlockStates -import org.bukkit.craftbukkit.v1_19_R3.block.data.CraftBlockData -import org.bukkit.craftbukkit.v1_19_R3.util.CraftMagicNumbers +import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock +import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockState +import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates +import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData +import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers /** * X and Z in real coordinates diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt index 83ae550435..065b443108 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt @@ -9,8 +9,8 @@ import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.ores.OldOreData import net.horizonsend.ion.server.features.ores.generation.PlanetOreSettings.Companion.STAR_BALANCE import net.horizonsend.ion.server.features.ores.storage.OreData -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.ORE_DATA +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ORE_DATA import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.minecraft.core.BlockPos import org.bukkit.Chunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt index 5a9ca42bd9..e151ba369c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.ores.storage import com.manya.pdc.base.array.StringArrayDataType -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.minecraft.core.BlockPos import org.bukkit.Material import org.bukkit.persistence.PersistentDataAdapterContext diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/BlockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/BlockData.kt index 3deae5438c..89f22cb2ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/BlockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/BlockData.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.space.data -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.BLOCK_ENTITY -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.BLOCK_STATE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.BLOCK_ENTITY +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.BLOCK_STATE import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtUtils diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt index 9da0dd0beb..b2ea55058c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.space.data -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.BLOCKS -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.PALETTE -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.Y +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.BLOCKS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.PALETTE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y import net.horizonsend.ion.server.miscellaneous.utils.component1 import net.horizonsend.ion.server.miscellaneous.utils.component2 import net.minecraft.core.BlockPos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/StoredChunkBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/StoredChunkBlocks.kt index 18c1ea4f43..3e15ed4f02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/StoredChunkBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/StoredChunkBlocks.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.space.data -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.Chunk import org.bukkit.persistence.PersistentDataAdapterContext diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt index 57f6e7c320..e41f24fe72 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.TextInputMenu.Companion.anvilInputText import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.validator.InputValidator import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.validator.ValidatorResult -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.castSpawnEntity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt index 3fffb99112..39747769ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt @@ -7,11 +7,11 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.LOCKED -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.X -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.Y -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.Z +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.runnable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt index 29dbf7e45e..56dbed8714 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt @@ -4,13 +4,13 @@ import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED import net.horizonsend.ion.server.miscellaneous.utils.runnable +import net.horizonsend.ion.server.miscellaneous.utils.spherePoints import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import net.minecraft.nbt.CompoundTag -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints import org.bukkit.Sound import org.bukkit.block.Chest import org.bukkit.entity.EntityType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt index 167f776a38..8deaf3917e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt @@ -4,8 +4,8 @@ import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.common.extensions.hint import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.castSpawnEntity import net.horizonsend.ion.server.miscellaneous.utils.toBlockPos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt index f2cfadf35f..2e78130125 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.space.encounters import fr.skytasul.guardianbeam.Laser import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.castSpawnEntity import net.horizonsend.ion.server.miscellaneous.utils.distance diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt index 7be4dc21f7..9728ac47a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt @@ -8,8 +8,8 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.runnable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt index 334cb9ee62..8f4ad33bcc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.space.encounters -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.ENCOUNTER -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ENCOUNTER +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.minecraft.nbt.CompoundTag import org.bukkit.NamespacedKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Infested.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Infested.kt index 4c2bbedb52..b96b3ce09c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Infested.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Infested.kt @@ -4,8 +4,8 @@ import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED import net.horizonsend.ion.server.miscellaneous.utils.runnable import net.minecraft.nbt.CompoundTag import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Passcode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Passcode.kt index 5710850777..f802eed6c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Passcode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Passcode.kt @@ -3,13 +3,13 @@ package net.horizonsend.ion.server.features.space.encounters import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.nations.gui.skullItem import net.horizonsend.ion.server.features.space.encounters.Encounters.createLootChest import net.horizonsend.ion.server.features.space.encounters.Encounters.setChestFlag -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE +import net.horizonsend.ion.server.miscellaneous.utils.MenuHelper import net.kyori.adventure.text.minimessage.MiniMessage.miniMessage import net.minecraft.nbt.CompoundTag -import net.horizonsend.ion.server.features.nations.gui.skullItem -import net.horizonsend.ion.server.miscellaneous.utils.MenuHelper import org.bukkit.Sound.BLOCK_NOTE_BLOCK_BASS import org.bukkit.Sound.BLOCK_NOTE_BLOCK_HARP import org.bukkit.Sound.BLOCK_NOTE_BLOCK_SNARE diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/SecondaryChest.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/SecondaryChest.kt index b224ea2388..ff863bd553 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/SecondaryChest.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/SecondaryChest.kt @@ -2,8 +2,8 @@ package net.horizonsend.ion.server.features.space.encounters import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.SECONDARY_CHEST_MONEY +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SECONDARY_CHEST_MONEY import net.horizonsend.ion.server.miscellaneous.utils.VAULT_ECO import net.minecraft.nbt.CompoundTag import org.bukkit.block.Chest diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt index a0ce1d17c7..65c481b077 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt @@ -2,10 +2,10 @@ package net.horizonsend.ion.server.features.space.encounters import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.runnable -import net.minecraft.nbt.CompoundTag import net.horizonsend.ion.server.miscellaneous.utils.spherePoints +import net.minecraft.nbt.CompoundTag import org.bukkit.Sound import org.bukkit.block.Chest import org.bukkit.event.player.PlayerInteractEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index 5c090e664e..b650524ac9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock @@ -13,7 +14,6 @@ import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWe import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt index 119103d989..d6a2ad3c62 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.features.starship.movement.RotationMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.distance diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt new file mode 100644 index 0000000000..3354be1745 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -0,0 +1,136 @@ +package net.horizonsend.ion.server.features.world + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.Chunk +import org.bukkit.World +import org.bukkit.event.EventHandler +import org.bukkit.event.world.ChunkLoadEvent +import org.bukkit.event.world.ChunkUnloadEvent +import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER_ARRAY +import java.util.LinkedList + +class IonChunk(val inner: Chunk) { + val locationKey = inner.chunkKey + + fun onLoad() { + loadMultiblocks() + } + + fun onUnload() { + save() + } + + fun save() { + saveMultiblocks() + } + + private val multiblockEntities: LinkedList = LinkedList() + + private fun loadMultiblocks() { + val serialized = inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) ?: return + + for (serializedMultiblockData in serialized) { + val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, inner.persistentDataContainer.adapterContext) + + val multiblock = stored.type as EntityMultiblock<*> + + val entity = multiblock.createEntity(stored, inner.world, stored.x, stored.y, stored.z) + + loadMultiblockEntity(entity) + } + } + + /** + * Save the multiblock data back into the chunk + **/ + private fun saveMultiblocks() { + val array = multiblockEntities.map { + PersistentMultiblockData.toPrimitive(it.store(), inner.persistentDataContainer.adapterContext) + }.toTypedArray() + + inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY, array) + } + + /** + * Add a new multiblock to the chunk data + **/ + fun addMultiblock(multiblock: Multiblock, x: Int, y: Int, z: Int) { + if (multiblock !is EntityMultiblock<*>) return + + val data = PersistentMultiblockData(x, y, z, multiblock) + + val entity = multiblock.createEntity(data, inner.world, x, y, z) + + multiblockEntities.add(entity) + } + + fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { + return multiblockEntities.firstOrNull { + it.x == x && it.y == y && it.z == z + } + } + + /** + * Loads a multiblock entity from storage + **/ + private fun loadMultiblockEntity(entity: MultiblockEntity) { + multiblockEntities.add(entity) + } + + /** + * Tick the stuff in the chunk + **/ + fun tick() { + multiblockEntities.forEach { it.tick() } + } + + companion object : SLEventListener() { + @EventHandler + fun onChunkLoad(event: ChunkLoadEvent) { + registerChunk(event.chunk) + } + + @EventHandler + fun onChunkUnload(event: ChunkUnloadEvent) { + unregisterChunk(event.chunk) + } + + /** + * Handles the creation, registration and loading of the chunk in the IonWorld + **/ + private fun registerChunk(chunk: Chunk): IonChunk { + val ionWorld = chunk.world.ion + + val ionChunk = IonChunk(chunk) + ionWorld.addChunk(ionChunk) + + ionChunk.onLoad() + + return ionChunk + } + + /** + * Handles the unloading of the chunk + **/ + private fun unregisterChunk(chunk: Chunk) { + val ionWorld = chunk.world.ion + + val removed = ionWorld.removeChunk(chunk) ?: return + + removed.onUnload() + } + + /** + * Returns the chunk at the specified coordinates in the world if it is loaded + **/ + operator fun get(world: World, x: Int, z: Int): IonChunk? { + return world.ion.getChunk(x, z) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index d0e24ff44d..9c5ea6db20 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.FORBIDDEN_BLOCKS import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.mainThreadCheck +import org.bukkit.Chunk import org.bukkit.World import org.bukkit.entity.Player import org.bukkit.event.EventHandler @@ -26,6 +27,53 @@ class IonWorld private constructor( val world: World, val starships: MutableList = mutableListOf() ) { + /** + * Key: The location of the chunk packed into a long + * + * Value: The IonChunk at that location + **/ + private val chunks: MutableMap = mutableMapOf() + + /** + * Gets the IonChunk at the specified coordinates if it is loaded + **/ + fun getChunk(x: Int, z: Int): IonChunk? { + val key = Chunk.getChunkKey(x, z) + + return chunks[key] + } + + /** + * Gets the IonChunk at the specified key if it is loaded + **/ + fun getChunk(key: Long): IonChunk? { + return chunks[key] + } + + /** + * Adds the chunk + **/ + fun addChunk(chunk: IonChunk) { + if (chunks.containsKey(chunk.locationKey)) { + log.warn("Attempted to add a chunk that was already in the map!") + } + + chunks[chunk.locationKey] = chunk + } + + /** + * Removes the chunk + ***/ + fun removeChunk(chunk: Chunk): IonChunk? { + val result = chunks.remove(chunk.chunkKey) + + if (result == null) { + log.warn("Chunk removed that was not in the map!") + } + + return result + } + /** * The world configuration * @@ -117,16 +165,25 @@ class IonWorld private constructor( fun onServerTickStartEvent(@Suppress("UNUSED_PARAMETER") event: ServerTickStartEvent) { mainThreadCheck() - for (ionWorld in ionWorlds.values) - for (starship in ionWorld.starships) { - val result = runCatching(starship::tick).exceptionOrNull() ?: continue - log.warn("Exception while ticking starship!", result) + for (ionWorld in ionWorlds.values) { + for (starship in ionWorld.starships) { + val result = runCatching(starship::tick).exceptionOrNull() ?: continue + log.warn("Exception while ticking starship!", result) + } + + for ((_, chunk) in ionWorld.chunks) { + chunk.tick() + } } } @EventHandler fun onWorldSave(event: WorldSaveEvent) { -// TODO + for (ionWorld in ionWorlds.values) { + for ((_, chunk) in ionWorld.chunks) { + chunk.save() + } + } } /** Gets the world's Ion counterpart */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/mobs/CustomMobSpawner.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/mobs/CustomMobSpawner.kt index b9915df00d..9c8af06b91 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/mobs/CustomMobSpawner.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/mobs/CustomMobSpawner.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.command.GlobalCompletions.fromItemString import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.WorldSettings -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.CUSTOM_ENTITY +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ENTITY import net.horizonsend.ion.server.miscellaneous.utils.weightedRandomOrNull import net.kyori.adventure.text.minimessage.MiniMessage import org.bukkit.entity.LivingEntity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generationUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generationUtils.kt index 25ef089cd3..cda4a6f7f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generationUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generationUtils.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.world.generation import net.horizonsend.ion.server.features.space.data.StoredChunkBlocks import net.horizonsend.ion.server.features.space.data.StoredChunkBlocks.Companion.place -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Chunk fun regenerateChunk(chunk: Chunk) = chunk.persistentDataContainer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/GenerateWreck.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/GenerateWreck.kt index 5f1f43fb72..d91f5ae0f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/GenerateWreck.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/GenerateWreck.kt @@ -7,9 +7,9 @@ import net.horizonsend.ion.server.features.space.data.BlockData import net.horizonsend.ion.server.features.space.data.CompletedSection import net.horizonsend.ion.server.features.space.encounters.Encounter import net.horizonsend.ion.server.features.space.encounters.SecondaryChest -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.ENCOUNTER -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.SECONDARY_CHEST -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.SECONDARY_CHEST_MONEY +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ENCOUNTER +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SECONDARY_CHEST +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SECONDARY_CHEST_MONEY import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.toBukkitBlockData import net.minecraft.nbt.CompoundTag diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt index 6c9e59cbc9..94ed020aca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.configuration.ServerConfiguration import net.horizonsend.ion.server.features.space.encounters.Encounters import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager import net.horizonsend.ion.server.features.world.generation.generators.interfaces.WorldGenerator -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.WeightedRandomList import net.horizonsend.ion.server.miscellaneous.utils.component1 import net.horizonsend.ion.server.miscellaneous.utils.component2 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/BiomeFixer9001.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/BiomeFixer9001.kt index ad0690d47a..940edbd2e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/BiomeFixer9001.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/BiomeFixer9001.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.listener.fixers import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Bukkit import org.bukkit.block.Biome import org.bukkit.event.EventHandler diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/EdenFixer9000.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/EdenFixer9000.kt index 184bd25bb1..8dcb2d6c5c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/EdenFixer9000.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/EdenFixer9000.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.listener.fixers import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.minecraft.core.BlockPos import org.bukkit.Bukkit import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index f1b08c7652..d319407530 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager import net.horizonsend.ion.server.features.waypoint.WaypointListeners +import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager import net.horizonsend.ion.server.listener.fixers.BiomeFixer9001 @@ -68,6 +69,8 @@ val listeners: List = listOf( GameplayTweaksListeners(), HeadListener(), HyperspaceBeaconManager, + IonWorld, + IonChunk, MiscListeners(), WorldGenerationManager, EncounterManager(), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/NamespacedKeys.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index e7a806081c..e6703c6ce4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.miscellaneous.registrations +package net.horizonsend.ion.server.miscellaneous.registrations.persistence import net.horizonsend.ion.server.IonServer import net.kyori.adventure.key.Key @@ -79,6 +79,8 @@ object NamespacedKeys { val FORBIDDEN_BLOCKS = key("forbidden_blocks") val CARGO_CRATE = key("cargo_crate") + val STORED_MULTIBLOCK_ENTITIES = key("storedMultiblocKEntities") + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt new file mode 100644 index 0000000000..10ed9cd022 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt @@ -0,0 +1,37 @@ +package net.horizonsend.ion.server.miscellaneous.registrations.persistence + +import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +class StoredPosition( + val x: Int, + val y: Int, + val z: Int +) { + constructor(vec3i: Vec3i) : this(vec3i.x, vec3i.y, vec3i.z) + + companion object : PersistentDataType { + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + override fun getComplexType(): Class = StoredPosition::class.java + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): StoredPosition { + val x = primitive.get(NamespacedKeys.X, PersistentDataType.INTEGER)!! + val y = primitive.get(NamespacedKeys.Y, PersistentDataType.INTEGER)!! + val z = primitive.get(NamespacedKeys.Z, PersistentDataType.INTEGER)!! + + return StoredPosition(x, y, z) + } + + override fun toPrimitive(complex: StoredPosition, context: PersistentDataAdapterContext): PersistentDataContainer { + val primitive = context.newPersistentDataContainer() + + primitive.set(NamespacedKeys.X, PersistentDataType.INTEGER, complex.x) + primitive.set(NamespacedKeys.Y, PersistentDataType.INTEGER, complex.y) + primitive.set(NamespacedKeys.Z, PersistentDataType.INTEGER, complex.z) + + return primitive + } + } +} From 57ac9f7cbfdefaef427747a8bf7829a5be10c41e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 7 Mar 2024 12:49:01 -0600 Subject: [PATCH 007/500] map to location keys --- .../ion/server/features/world/IonChunk.kt | 24 +++++++++++-------- .../server/miscellaneous/utils/NewBlockKey.kt | 9 +++++++ 2 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 3354be1745..3814797f43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -7,13 +7,14 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.Entity import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey import org.bukkit.Chunk import org.bukkit.World import org.bukkit.event.EventHandler import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER_ARRAY -import java.util.LinkedList +import java.util.concurrent.ConcurrentHashMap class IonChunk(val inner: Chunk) { val locationKey = inner.chunkKey @@ -30,7 +31,7 @@ class IonChunk(val inner: Chunk) { saveMultiblocks() } - private val multiblockEntities: LinkedList = LinkedList() + private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() private fun loadMultiblocks() { val serialized = inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) ?: return @@ -50,8 +51,8 @@ class IonChunk(val inner: Chunk) { * Save the multiblock data back into the chunk **/ private fun saveMultiblocks() { - val array = multiblockEntities.map { - PersistentMultiblockData.toPrimitive(it.store(), inner.persistentDataContainer.adapterContext) + val array = multiblockEntities.map { (_, entity) -> + PersistentMultiblockData.toPrimitive(entity.store(), inner.persistentDataContainer.adapterContext) }.toTypedArray() inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY, array) @@ -67,27 +68,30 @@ class IonChunk(val inner: Chunk) { val entity = multiblock.createEntity(data, inner.world, x, y, z) - multiblockEntities.add(entity) + val key = toBlockKey(x, y, z) + multiblockEntities[key] = entity } fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { - return multiblockEntities.firstOrNull { - it.x == x && it.y == y && it.z == z - } + val key = toBlockKey(x, y, z) + + return multiblockEntities[key] } /** * Loads a multiblock entity from storage **/ private fun loadMultiblockEntity(entity: MultiblockEntity) { - multiblockEntities.add(entity) + val key = toBlockKey(entity.x, entity.y, entity.z) + + multiblockEntities[key] = entity } /** * Tick the stuff in the chunk **/ fun tick() { - multiblockEntities.forEach { it.tick() } + multiblockEntities.forEach { (_, entity) -> entity.tick() } } companion object : SLEventListener() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt new file mode 100644 index 0000000000..3799997615 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.miscellaneous.utils + +import net.minecraft.core.BlockPos + +/** + * Packs a x, y, z coordinate into a long + **/ +fun toBlockKey(x: Int, y: Int, z: Int): Long = BlockPos.asLong(x, y, z) +fun toVec3i(key: Long): Vec3i = Vec3i(BlockPos.getX(key), BlockPos.getY(key), BlockPos.getZ(key)) From 213dfed184b1efc35b726efd19bde39f2de5ece5 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 7 Mar 2024 13:43:10 -0600 Subject: [PATCH 008/500] clean up, start of reimplementation of power --- .../{ => entity}/MultiblockEntity.kt | 13 +- .../{ => entity}/PersistentMultiblockData.kt | 6 +- .../entity/PoweredMultiblockEntity.kt | 71 ++++++++ .../multiblock/type/TickingMultiblock.kt | 16 ++ .../multiblock/type/misc/TestMultiblock.kt | 4 +- .../type/starshipweapon/EntityMultiblock.kt | 4 +- .../ion/server/features/world/IonChunk.kt | 155 +++++++++++------- 7 files changed, 193 insertions(+), 76 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{ => entity}/MultiblockEntity.kt (88%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{ => entity}/PersistentMultiblockData.kt (90%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt similarity index 88% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 1128e7bb7b..acbd1eef5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,5 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock +package net.horizonsend.ion.server.features.multiblock.entity +import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import org.bukkit.Location import org.bukkit.World @@ -48,14 +49,4 @@ abstract class MultiblockEntity( return store } - - /** - * Called upon world tick - **/ - fun tick() {} - - /** - * Called upon world tick. - **/ - fun tickAsync() {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index 3b427feabf..ec2d499ee9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -1,6 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock +package net.horizonsend.ion.server.features.multiblock.entity import kotlinx.serialization.SerializationException +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ADDITIONAL_MULTIBLOCK_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X @@ -17,7 +19,7 @@ import org.bukkit.persistence.PersistentDataType.STRING import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Multiblock) { - constructor(x: Int, y: Int, z: Int, type: Multiblock, additionalData: PersistentDataContainer) : this(x, y, z, type) { + constructor(x: Int, y: Int, z: Int, type: Multiblock, additionalData: PersistentDataContainer) : this(x, y, z, type) { this.additionalData = additionalData } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt new file mode 100644 index 0000000000..5d601d5b8d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt @@ -0,0 +1,71 @@ +package net.horizonsend.ion.server.features.multiblock.entity + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.World +import org.bukkit.block.Sign + +abstract class PoweredMultiblockEntity( + x: Int, + y: Int, + z: Int, + world: World, + type: Multiblock, + private var power: Int +) : MultiblockEntity(x, y, z, world, type) { + init { + require(type is PowerStoringMultiblock) + } + + val maxPower = (type as PowerStoringMultiblock).maxPower + + private val prefixComponent = Component.text("E: ", NamedTextColor.YELLOW) + + fun setPower(amount: Int) { + val correctedPower = amount.coerceIn(0, maxPower) + + power = correctedPower + } + + fun getPower(): Int { + return power + } + + /** + * Returns the amount of power that could not be added + **/ + fun addPower(sign: Sign, amount: Int): Int { + val newAmount = getPower() + amount + + setPower(newAmount) + + return if (newAmount > maxPower) maxPower - newAmount else 0 + } + + /** + * Returns the amount of power that could not be removed + **/ + fun removePower(amount: Int): Int { + val newAmount = getPower() - amount + + setPower(newAmount) + + return if (newAmount < 0) newAmount else 0 + } + + /** + * Returns whether this multiblock has the capacity to fit the specified amount of power + **/ + fun canFitPower(amount: Int): Boolean { + return getPower() + amount < maxPower + } + + /** + * Returns true if this amount of power can be removed without reaching zero. + **/ + fun canRemovePower(amount: Int): Boolean { + return getPower() - amount > 0 + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt new file mode 100644 index 0000000000..f8f7f53b13 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt @@ -0,0 +1,16 @@ +package net.horizonsend.ion.server.features.multiblock.type + +/** + * Any multiblock that should be ticked along with the world + **/ +interface TickingMultiblock { + /** + * Whether the tick should be run async + **/ + val tickAsync: Boolean + + /** + * The logic that is run upon world tick + **/ + fun tick() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index d624b25262..7948812148 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -4,9 +4,9 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt index 635f02fc08..1fac7c14fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon -import net.horizonsend.ion.server.features.multiblock.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 3814797f43..847d9d1ac7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -1,8 +1,11 @@ package net.horizonsend.ion.server.features.world +import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.type.TickingMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener @@ -16,82 +19,41 @@ import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER_ARRAY import java.util.concurrent.ConcurrentHashMap -class IonChunk(val inner: Chunk) { +class IonChunk(private val inner: Chunk) { val locationKey = inner.chunkKey - fun onLoad() { - loadMultiblocks() - } - - fun onUnload() { - save() - } - - fun save() { - saveMultiblocks() - } - - private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + //TODO + // - Wires + // - Ore upgrade + // - - private fun loadMultiblocks() { - val serialized = inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) ?: return - - for (serializedMultiblockData in serialized) { - val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, inner.persistentDataContainer.adapterContext) - - val multiblock = stored.type as EntityMultiblock<*> - - val entity = multiblock.createEntity(stored, inner.world, stored.x, stored.y, stored.z) - - loadMultiblockEntity(entity) - } - } /** - * Save the multiblock data back into the chunk + * Logic upon loading the chunk **/ - private fun saveMultiblocks() { - val array = multiblockEntities.map { (_, entity) -> - PersistentMultiblockData.toPrimitive(entity.store(), inner.persistentDataContainer.adapterContext) - }.toTypedArray() - - inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY, array) + fun onLoad() { + loadMultiblocks() } /** - * Add a new multiblock to the chunk data + * Logic upon unloading the chunk **/ - fun addMultiblock(multiblock: Multiblock, x: Int, y: Int, z: Int) { - if (multiblock !is EntityMultiblock<*>) return - - val data = PersistentMultiblockData(x, y, z, multiblock) - - val entity = multiblock.createEntity(data, inner.world, x, y, z) - - val key = toBlockKey(x, y, z) - multiblockEntities[key] = entity - } - - fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { - val key = toBlockKey(x, y, z) - - return multiblockEntities[key] + fun onUnload() { + save() } /** - * Loads a multiblock entity from storage + * Logic upon world save **/ - private fun loadMultiblockEntity(entity: MultiblockEntity) { - val key = toBlockKey(entity.x, entity.y, entity.z) - - multiblockEntities[key] = entity + fun save() { + saveMultiblocks() } /** - * Tick the stuff in the chunk + * Logic upon world tick **/ fun tick() { - multiblockEntities.forEach { (_, entity) -> entity.tick() } + tickMultiblocks() } companion object : SLEventListener() { @@ -137,4 +99,79 @@ class IonChunk(val inner: Chunk) { return world.ion.getChunk(x, z) } } + + private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + private val tickingMultiblocks: ConcurrentHashMap = ConcurrentHashMap() + + /** + * Add a new multiblock to the chunk data + **/ + fun addMultiblock(multiblock: Multiblock, x: Int, y: Int, z: Int) { + val key = toBlockKey(x, y, z) + + if (multiblock is TickingMultiblock) { + tickingMultiblocks[key] = multiblock + } + + if (multiblock !is EntityMultiblock<*>) return + + val data = PersistentMultiblockData(x, y, z, multiblock) + + val entity = multiblock.createEntity(data, inner.world, x, y, z) + + multiblockEntities[key] = entity + } + + fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { + val key = toBlockKey(x, y, z) + + return multiblockEntities[key] + } + + private fun tickMultiblocks() { + tickingMultiblocks.values.forEach { + if (it.tickAsync) { + Multiblocks.context.launch { it.tick() } + } else { + it.tick() + } + } + } + + /** + * Load the multiblocks from the persistent data container upon chunk load. + **/ + private fun loadMultiblocks() { + val serialized = inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) ?: return + + for (serializedMultiblockData in serialized) { + val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, inner.persistentDataContainer.adapterContext) + + val multiblock = stored.type as EntityMultiblock<*> + + val entity = multiblock.createEntity(stored, inner.world, stored.x, stored.y, stored.z) + + loadMultiblockEntity(entity) + } + } + + /** + * Loads a multiblock entity from storage + **/ + private fun loadMultiblockEntity(entity: MultiblockEntity) { + val key = toBlockKey(entity.x, entity.y, entity.z) + + multiblockEntities[key] = entity + } + + /** + * Save the multiblock data back into the chunk + **/ + private fun saveMultiblocks() { + val array = multiblockEntities.map { (_, entity) -> + PersistentMultiblockData.toPrimitive(entity.store(), inner.persistentDataContainer.adapterContext) + }.toTypedArray() + + inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY, array) + } } From 0d6327de2ab1e243efbfe869b3d6259ab7badc2e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 7 Mar 2024 14:35:15 -0600 Subject: [PATCH 009/500] utility, more power work --- .../starship/active/ActiveStarshipHitbox.java | 17 +- .../blockplacement/BlockPlacementRaw.java | 6 +- .../server/command/admin/IonChunkCommand.kt | 40 ++++ .../server/command/economy/CityNpcCommand.kt | 6 +- .../server/command/misc/MultiblockCommand.kt | 36 ++- .../server/command/misc/RegenerateCommand.kt | 2 +- .../command/nations/SpaceStationCommand.kt | 2 +- .../settlementZones/SettlementZoneCommand.kt | 2 +- .../command/qol/FixExtractorsCommand.kt | 2 +- .../ion/server/command/space/StarCommand.kt | 3 +- .../command/starship/BlueprintCommand.kt | 12 +- .../command/starship/StarshipDebugCommand.kt | 4 +- .../command/starship/StarshipInfoCommand.kt | 2 +- .../configuration/ServerConfiguration.kt | 1 + .../features/ai/AIControllerFactories.kt | 4 +- .../ion/server/features/ai/module/AIModule.kt | 2 +- .../features/ai/module/combat/CombatModule.kt | 2 +- .../ai/module/combat/FrigateCombatModule.kt | 6 +- .../module/combat/StarfighterCombatModule.kt | 6 +- .../features/ai/module/misc/FleeModule.kt | 2 +- .../ai/module/movement/CruiseModule.kt | 14 +- .../ai/module/movement/MovementModule.kt | 10 +- .../module/pathfinding/PathfindingModule.kt | 2 +- .../pathfinding/SteeringPathfindingModule.kt | 4 +- .../AxisStandoffPositioningModule.kt | 4 +- .../positioning/BasicPositioningModule.kt | 2 +- .../positioning/CirclingPositionModule.kt | 2 +- .../module/positioning/PositioningModule.kt | 2 +- .../positioning/StandoffPositioningModule.kt | 2 +- .../features/ai/spawning/AISpawningUtils.kt | 16 +- .../features/ai/spawning/SpawningException.kt | 2 +- .../ion/server/features/ai/util/AITarget.kt | 4 +- .../client/display/ClientDisplayEntities.kt | 2 +- .../type/weapon/blaster/BlasterProjectile.kt | 2 +- .../features/economy/collectors/Collectors.kt | 2 +- .../server/features/machine/AreaShields.kt | 2 +- .../ion/server/features/machine/CryoPods.kt | 2 +- .../machine/decomposer/Decomposers.kt | 2 +- .../ion/server/features/misc/Shuttles.kt | 4 +- .../features/misc/UnusedSoldShipPurge.kt | 6 +- .../server/features/multiblock/Multiblock.kt | 54 +++-- .../features/multiblock/MultiblockShape.kt | 11 +- .../server/features/multiblock/Multiblocks.kt | 223 ++++++++++-------- .../multiblock/entity/MultiblockEntity.kt | 25 +- .../entity/PersistentMultiblockData.kt | 18 +- .../entity/PoweredMultiblockEntity.kt | 4 +- .../TickingMultiblockEntity.kt} | 6 +- .../multiblock/type/InteractableMultiblock.kt | 40 ++++ .../multiblock/type/areashield/AreaShield.kt | 4 +- .../type/defense/AntiAirCannonMultiblock.kt | 2 +- .../ConnectedDockingTubeMultiblock.kt | 2 +- .../DisconnectedDockingTubeMultiblock.kt | 2 +- .../type/dockingtube/DockingTubeMultiblock.kt | 2 +- .../multiblock/type/farming/CropMultiblock.kt | 2 +- .../farming/harvester/HarvesterMultiblock.kt | 2 +- .../type/farming/planter/PlanterMultiblock.kt | 2 +- .../type/gas/GasPowerPlantMultiblock.kt | 2 +- .../type/hyperdrive/HyperdriveMultiblock.kt | 4 +- .../hyperdrive/HyperdriveMultiblockClass1.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass2.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass3.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass4.kt | 2 +- .../mininglasers/MiningLaserMultiblock.kt | 2 +- .../MiningLaserMultiblockTier1.kt | 2 +- .../MiningLaserMultiblockTier2.kt | 2 +- .../MiningLaserMultiblockTier3.kt | 2 +- .../MiningLaserMultiblockTier4.kt | 2 +- .../multiblock/type/misc/CryoPodMultiblock.kt | 2 +- .../type/misc/ItemSplitterMultiblock.kt | 2 +- .../type/misc/LandingGearMultiblock.kt | 4 +- .../type/misc/OdometerMultiblock.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 51 +++- .../type/misc/TractorBeamMultiblock.kt | 2 +- .../particleshield/BoxShieldMultiblock.kt | 2 +- .../type/particleshield/ShieldMultiblock.kt | 4 +- .../particleshield/ShieldMultiblockClass20.kt | 4 +- .../particleshield/SphereShieldMultiblock.kt | 4 +- .../type/starshipweapon/EntityMultiblock.kt | 3 +- .../SignlessStarshipWeaponMultiblock.kt | 2 +- .../starshipweapon/SubsystemMultiblock.kt | 2 +- .../LaserCannonStarshipWeaponMultiblock.kt | 2 +- .../PlasmaCannonStarshipWeaponMultiblock.kt | 2 +- .../PulseCannonStarshipWeaponMultiblock.kt | 2 +- .../CapitalBeamStarshipWeaponMultiblock.kt | 2 +- .../event/CthulhuBeamMultiblock.kt | 2 +- .../FlamethrowerStarshipWeaponMultiblock.kt | 2 +- .../MiniPhaserStarshipWeaponMultiblock.kt | 2 +- .../PumpkinCannonStarshipWeaponMultiblock.kt | 2 +- .../event/SonicMissileWeaponMultiblock.kt | 2 +- .../AIHeavyLaserStarshipWeaponMultiblock.kt | 2 +- .../ArsenalRocketStarshipWeaponMultiblock.kt | 2 +- .../HeavyLaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/PhaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/RocketStarshipWeaponMultiblock.kt | 2 +- .../heavy/TorpedoStarshipWeaponMultiblock.kt | 2 +- .../PointDefenseStarshipWeaponMultiblock.kt | 2 +- .../turret/HeavyTurretMultiblock.kt | 2 +- .../turret/IonTurretMultiblock.kt | 2 +- .../turret/LightTurretMultiblock.kt | 2 +- .../turret/QuadTurretMultiblock.kt | 2 +- .../turret/RotatingMultiblock.kt | 14 +- .../turret/TriTurretMultiblock.kt | 2 +- .../starshipweapon/turret/TurretMultiblock.kt | 4 +- .../multiblock/util/AsyncBlockUtils.kt | 13 +- .../features/multiblock/util/BlockSnapshot.kt | 7 +- .../region/types/RegionCapturableStation.kt | 2 +- .../region/types/RegionSettlementZone.kt | 2 +- .../region/types/RegionSpaceStation.kt | 2 +- .../ion/server/features/npcs/NPCManager.kt | 2 +- .../server/features/npcs/StarshipDealers.kt | 2 +- .../server/features/player/DutyModeMonitor.kt | 2 +- .../sidebar/command/BookmarkCommand.kt | 2 +- .../ion/server/features/space/Space.kt | 2 + .../server/features/space/body/CachedStar.kt | 4 +- .../features/space/body/CelestialBody.kt | 4 +- .../features/space/data/CompletedSection.kt | 4 +- .../space/encounters/BridgeOfDeath.kt | 2 +- .../features/space/encounters/CoolantLeak.kt | 6 +- .../features/space/encounters/CowTipper.kt | 2 +- .../features/space/encounters/DefenseBots.kt | 4 +- .../space/encounters/DefenseMatrix.kt | 4 +- .../features/space/encounters/DefuseBomb.kt | 8 +- .../features/space/encounters/Encounters.kt | 2 +- .../features/space/encounters/TimedBomb.kt | 2 +- .../features/starship/AutoTurretTargeting.kt | 2 +- .../starship/DeactivatedPlayerStarships.kt | 2 +- .../starship/DeactivatedShipWorldCache.kt | 6 +- .../ion/server/features/starship/Hangars.kt | 6 +- .../features/starship/PilotedStarships.kt | 8 +- .../ion/server/features/starship/Starship.kt | 10 +- .../features/starship/StarshipDetection.kt | 12 +- .../features/starship/StarshipSchematic.kt | 2 +- .../server/features/starship/StarshipState.kt | 12 +- .../starship/active/ActiveStarshipFactory.kt | 8 +- .../active/ActiveStarshipMechanics.kt | 2 +- .../starship/active/ActiveStarships.kt | 4 +- .../starship/active/StarshipDisplay.kt | 14 +- .../starship/active/SubsystemDetector.kt | 5 +- .../control/controllers/Controller.kt | 2 +- .../control/controllers/ai/AIController.kt | 2 +- .../control/movement/AIControlUtils.kt | 6 +- .../control/movement/StarshipControl.kt | 1 + .../destruction/StandardSinkProvider.kt | 12 +- .../starship/factory/StarshipFactories.kt | 2 +- .../factory/StarshipFactoryPrinter.kt | 8 +- .../starship/hyperspace/HyperspaceMovement.kt | 2 +- .../starship/hyperspace/MassShadows.kt | 2 +- .../starship/movement/OptimizedMovement.kt | 14 +- .../starship/movement/StarshipMovement.kt | 10 +- .../movement/StarshipMovementException.kt | 2 +- .../movement/StarshipTeleportation.kt | 2 +- .../starship/movement/TranslateMovement.kt | 2 +- .../subsystem/AbstractMultiblockSubsystem.kt | 2 +- .../starship/subsystem/StarshipSubsystem.kt | 2 +- .../subsystem/misc/LandingGearSubsystem.kt | 2 +- .../subsystem/misc/MiningLaserSubsystem.kt | 2 +- .../subsystem/misc/OdometerSubsystem.kt | 4 +- .../subsystem/shield/BoxShieldSubsystem.kt | 2 +- .../subsystem/shield/SphereShieldSubsystem.kt | 2 +- .../subsystem/shield/StarshipShields.kt | 10 +- .../subsystem/thruster/ThrusterSubsystem.kt | 2 +- .../subsystem/weapon/CannonWeaponSubsystem.kt | 2 +- .../TargetTrackingCannonWeaponSubsystem.kt | 2 +- .../subsystem/weapon/TurretWeaponSubsystem.kt | 4 +- .../subsystem/weapon/WeaponSubsystem.kt | 2 +- .../event/CapitalBeamWeaponSubsystem.kt | 6 +- .../event/CthulhuBeamWeaponSubsystem.kt | 2 +- .../event/FlamethrowerWeaponSubsystem.kt | 2 +- .../weapon/event/MiniPhaserWeaponSubsystem.kt | 2 +- .../event/PumpkinCannonWeaponSubsystem.kt | 10 +- .../event/SonicMissileWeaponSubsystem.kt | 2 +- .../projectile/CapitalBeamCannonProjectile.kt | 2 +- .../projectile/PumpkinCannonProjectile.kt | 2 +- .../primary/HeavyTurretWeaponSubsystem.kt | 2 +- .../primary/IonTurretWeaponSubsystem.kt | 2 +- .../primary/LaserCannonWeaponSubsystem.kt | 2 +- .../primary/LightTurretWeaponSubsystem.kt | 2 +- .../primary/PlasmaCannonWeaponSubsystem.kt | 2 +- .../weapon/primary/PointDefenseSubsystem.kt | 2 +- .../primary/PulseCannonWeaponSubsystem.kt | 2 +- .../primary/QuadTurretWeaponSubsystem.kt | 2 +- .../projectile/ArsenalRocketProjectile.kt | 2 +- .../weapon/projectile/BlockProjectile.kt | 2 +- .../weapon/projectile/IonTurretProjectile.kt | 3 +- .../weapon/projectile/RocketProjectile.kt | 2 +- .../weapon/projectile/VisualProjectile.kt | 2 +- .../secondary/AIHeavyLaserWeaponSubsystem.kt | 2 +- .../ArsenalRocketStarshipWeaponSubsystem.kt | 2 +- .../secondary/HeavyLaserWeaponSubsystem.kt | 2 +- .../weapon/secondary/PhaserWeaponSubsystem.kt | 2 +- .../weapon/secondary/RocketWeaponSubsystem.kt | 3 +- .../secondary/TorpedoWeaponSubsystem.kt | 2 +- .../secondary/TriTurretWeaponSubsystem.kt | 2 +- .../features/transport/ChunkPowerNetwork.kt | 38 +++ .../features/transport/ExtractorData.kt | 31 +++ .../server/features/transport/Extractors.kt | 4 +- .../ion/server/features/transport/Wires.kt | 2 +- .../features/transport/pipe/PipeChainData.kt | 2 +- .../server/features/transport/pipe/Pipes.kt | 10 +- .../transport/pipe/filter/FilterDataKey.kt | 2 +- .../features/transport/pipe/filter/Filters.kt | 2 +- .../tutorial/tutorials/FlightTutorial.kt | 2 +- .../ion/server/features/world/IonChunk.kt | 95 ++++++-- .../ion/server/features/world/IonWorld.kt | 3 +- .../features/world/environment/Environment.kt | 2 +- .../generators/space/SpaceGenerator.kt | 6 +- .../fixers/GameplayTweaksListeners.kt | 8 +- .../server/listener/misc/InteractListener.kt | 25 +- .../listener/misc/ProtectionListener.kt | 11 +- .../miscellaneous/registrations/Commands.kt | 2 + .../miscellaneous/registrations/Listeners.kt | 4 +- .../persistence/NamespacedKeys.kt | 8 +- .../persistence/StoredPosition.kt | 2 +- .../miscellaneous/utils/Miscellaneous.kt | 2 + .../ion/server/miscellaneous/utils/NMS.kt | 1 + .../server/miscellaneous/utils/NewBlockKey.kt | 2 + .../miscellaneous/utils/ServerDBBridge.kt | 43 ---- .../server/miscellaneous/utils/WorldEdit.kt | 2 + .../utils/{ => coordinates}/Coordinates.kt | 2 +- .../miscellaneous/utils/coordinates/Vec3i.kt | 47 ++++ 220 files changed, 933 insertions(+), 581 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type/TickingMultiblock.kt => entity/TickingMultiblockEntity.kt} (63%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt rename server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/{ => coordinates}/Coordinates.kt (99%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt diff --git a/server/src/main/java/net/starlegacy/feature/starship/active/ActiveStarshipHitbox.java b/server/src/main/java/net/starlegacy/feature/starship/active/ActiveStarshipHitbox.java index 45af06c583..fea204b49b 100644 --- a/server/src/main/java/net/starlegacy/feature/starship/active/ActiveStarshipHitbox.java +++ b/server/src/main/java/net/starlegacy/feature/starship/active/ActiveStarshipHitbox.java @@ -1,6 +1,7 @@ package net.starlegacy.feature.starship.active; -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i; +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.CoordinatesKt; +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i; import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -51,9 +52,9 @@ public void calculateBounds(@NotNull Set blocks) { boundsArray = new int[width][][]; for (long key : blocks) { - int x = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyX(key) - minX; - int y = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyY(key) - minY; - int z = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyZ(key) - minZ; + int x = CoordinatesKt.blockKeyX(key) - minX; + int y = CoordinatesKt.blockKeyY(key) - minY; + int z = CoordinatesKt.blockKeyZ(key) - minZ; int[][] yBoundsArray = boundsArray[x]; @@ -84,13 +85,13 @@ public void calculateMinMax(Set blocks) { } long start = blocks.iterator().next(); - int minX = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyX(start), minY = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyY(start), minZ = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyZ(start); + int minX = CoordinatesKt.blockKeyX(start), minY = CoordinatesKt.blockKeyY(start), minZ = CoordinatesKt.blockKeyZ(start); int maxX = minX, maxY = minY, maxZ = minZ; for (long key : blocks) { - int x = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyX(key); - int y = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyY(key); - int z = net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.blockKeyZ(key); + int x = CoordinatesKt.blockKeyX(key); + int y = CoordinatesKt.blockKeyY(key); + int z = CoordinatesKt.blockKeyZ(key); if (x < minX) minX = x; if (x > maxX) maxX = x; diff --git a/server/src/main/java/net/starlegacy/javautil/blockplacement/BlockPlacementRaw.java b/server/src/main/java/net/starlegacy/javautil/blockplacement/BlockPlacementRaw.java index 835048e4f5..5ae64adef0 100644 --- a/server/src/main/java/net/starlegacy/javautil/blockplacement/BlockPlacementRaw.java +++ b/server/src/main/java/net/starlegacy/javautil/blockplacement/BlockPlacementRaw.java @@ -3,8 +3,8 @@ import com.google.common.base.Preconditions; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.horizonsend.ion.server.IonServer; -import net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt; import net.horizonsend.ion.server.miscellaneous.utils.MiscellaneousKt; +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.CoordinatesKt; import net.minecraft.core.BlockPos; import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; import net.minecraft.server.level.ChunkHolder; @@ -31,8 +31,8 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import static net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.chunkKeyX; -import static net.horizonsend.ion.server.miscellaneous.utils.CoordinatesKt.chunkKeyZ; +import static net.horizonsend.ion.server.miscellaneous.utils.coordinates.CoordinatesKt.chunkKeyX; +import static net.horizonsend.ion.server.miscellaneous.utils.coordinates.CoordinatesKt.chunkKeyZ; public class BlockPlacementRaw { private final Logger log = IonServer.INSTANCE.getSLF4JLogger(); diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt new file mode 100644 index 0000000000..a1625e51e8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -0,0 +1,40 @@ +package net.horizonsend.ion.server.command.admin + +import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.Optional +import co.aikar.commands.annotation.Subcommand +import net.horizonsend.ion.common.utils.text.formatPaginatedMenu +import net.horizonsend.ion.server.command.SLCommand +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.world.IonChunk.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.toVec3i +import net.kyori.adventure.text.Component.text +import org.bukkit.entity.Player + +@CommandAlias("ionchunk") +object IonChunkCommand : SLCommand() { + @Subcommand("dumpEntities") + fun onDumpEntities(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { + val entities = sender.chunk.ion().getAllMultiblockEntities().toList() + + sender.sendMessage(formatPaginatedMenu( + entities.size, + "/ionchunk dumpentities ${visual ?: false}", + page ?: 1, + ) { index -> + val (key, entity) = entities[index] + + val vec = toVec3i(key) + + text("$vec : ${entity.type}") + }) + + if (visual == true) { + for ((key, _) in entities) { + val vec = toVec3i(key) + + sender.highlightBlock(vec, 30L) + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/economy/CityNpcCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/economy/CityNpcCommand.kt index 43185b7aaf..5263b6ddd6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/economy/CityNpcCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/economy/CityNpcCommand.kt @@ -5,11 +5,11 @@ import co.aikar.commands.PaperCommandManager import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Subcommand -import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.database.schema.economy.CityNPC import net.horizonsend.ion.common.database.schema.misc.SLPlayer import net.horizonsend.ion.common.database.uuid +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.economy.city.CityNPCs import net.horizonsend.ion.server.features.economy.city.TradeCities import net.horizonsend.ion.server.features.economy.city.TradeCityData @@ -17,7 +17,7 @@ import net.horizonsend.ion.server.features.economy.city.TradeCityType import net.horizonsend.ion.server.features.nations.region.Regions import net.horizonsend.ion.server.features.nations.region.types.RegionTerritory import net.horizonsend.ion.server.miscellaneous.utils.Skins -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.command.CommandSender diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index f9e5173caa..fd5babd149 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -9,14 +9,20 @@ import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.displayBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.event.ClickEvent +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.TextDecoration import org.bukkit.block.Block import org.bukkit.block.Sign import org.bukkit.entity.Player @@ -41,6 +47,34 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { Multiblocks.all().joinToString("|") { it.javaClass.simpleName }) } + /** + * Prompt the player to use the multiblock command + **/ + fun setupCommand(player: Player, sign: Sign, lastMatch: Multiblock) { + val multiblockType = lastMatch.name + + val possibleTiers = Multiblocks.all().filter { it.name == multiblockType } + + val message = Component.text() + .append(Component.text("Which type of $multiblockType are you trying to build? (Click one)")) + .append(Component.newline()) + + for (tier in possibleTiers) { + val tierName = tier.javaClass.simpleName + + val command = "/multiblock check $tierName ${sign.x} ${sign.y} ${sign.z}" + + val tierText = bracketed(Component.text(tierName, NamedTextColor.DARK_GREEN, TextDecoration.BOLD)) + .clickEvent(ClickEvent.runCommand(command)) + .hoverEvent(Component.text(command).asHoverEvent()) + + message.append(tierText) + if (possibleTiers.indexOf(tier) != possibleTiers.size - 1) message.append(Component.text(", ")) + } + + player.sendMessage(message.build()) + } + @Subcommand("check") @CommandCompletion("@multiblocks") @CommandPermission("ion.multiblock.check") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt index 0e57d71ca8..551a16f8be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt @@ -24,7 +24,7 @@ import net.horizonsend.ion.server.features.space.data.BlockData import net.horizonsend.ion.server.features.space.data.CompletedSection import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getSelection import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.audience.Audience diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/SpaceStationCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/SpaceStationCommand.kt index d3ff77075b..45d688b8a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/SpaceStationCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/SpaceStationCommand.kt @@ -48,7 +48,7 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.VAULT_ECO -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/settlementZones/SettlementZoneCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/settlementZones/SettlementZoneCommand.kt index 267511f5c2..2fbb27520b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/settlementZones/SettlementZoneCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/settlementZones/SettlementZoneCommand.kt @@ -31,7 +31,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.MenuHelper import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.action import net.horizonsend.ion.server.miscellaneous.utils.colorize import net.horizonsend.ion.server.miscellaneous.utils.msg diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt index eee1269c00..6a78bf6e40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.transport.Extractors -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt index d6f2622d26..01ab654918 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt @@ -16,7 +16,8 @@ import net.horizonsend.ion.server.features.space.body.CachedStar import net.horizonsend.ion.server.features.space.body.OrbitingCelestialBody import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.features.space.SpaceWorlds +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.orNull import org.bukkit.Material import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/BlueprintCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/BlueprintCommand.kt index 93bbe643eb..461ef35702 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/BlueprintCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/BlueprintCommand.kt @@ -34,7 +34,7 @@ import net.horizonsend.ion.server.features.starship.factory.StarshipFactories import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.actualType import net.horizonsend.ion.server.miscellaneous.utils.createData import net.horizonsend.ion.server.miscellaneous.utils.loadClipboard @@ -317,11 +317,11 @@ object BlueprintCommand : net.horizonsend.ion.server.command.SLCommand() { } fun tryPilot( - sender: Player, - origin: Vec3i, - type: StarshipType, - name: String, - callback: (ActiveControlledStarship) -> Unit = {} + sender: Player, + origin: Vec3i, + type: StarshipType, + name: String, + callback: (ActiveControlledStarship) -> Unit = {} ) { val block = sender.world.getBlockAtKey(origin.toBlockKey()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt index 1ba570f8c8..24c7a12d5d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt @@ -22,8 +22,8 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipTeleportati import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.VariableVisualProjectile import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.VisualProjectile import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.helixAroundVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.helixAroundVector import org.bukkit.Color import org.bukkit.Location import org.bukkit.Particle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipInfoCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipInfoCommand.kt index d82ab91446..7bfc6e43bc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipInfoCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipInfoCommand.kt @@ -4,8 +4,8 @@ import co.aikar.commands.annotation.CommandAlias import net.horizonsend.ion.server.features.starship.Interdiction import net.horizonsend.ion.server.features.starship.StarshipDetection import net.horizonsend.ion.server.features.starship.hyperspace.Hyperspace -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.actualType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isConcrete import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ServerConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ServerConfiguration.kt index d338fd4823..cbe93ac0e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ServerConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ServerConfiguration.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.server.features.starship.StarshipType import net.horizonsend.ion.server.features.world.WorldSettings import net.horizonsend.ion.server.miscellaneous.utils.WeightedRandomList import net.horizonsend.ion.server.miscellaneous.utils.actualType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.readSchematic import net.minecraft.world.level.block.state.BlockState diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/AIControllerFactories.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/AIControllerFactories.kt index adb92d64da..bbc8d8368e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/AIControllerFactories.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/AIControllerFactories.kt @@ -22,8 +22,8 @@ import net.horizonsend.ion.server.features.ai.module.targeting.HighestDamagerTar import net.horizonsend.ion.server.features.ai.module.targeting.TargetingModule import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.distanceToVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceToVector import net.horizonsend.ion.server.miscellaneous.utils.orNull import java.util.Optional import kotlin.random.Random diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/AIModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/AIModule.kt index 587c0a05ba..8c6f6cc83a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/AIModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/AIModule.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.starship.control.controllers.ai.AICon import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Location import org.slf4j.Logger import org.slf4j.LoggerFactory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/CombatModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/CombatModule.kt index 9a0e074877..daed8a10fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/CombatModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/CombatModule.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.control.controllers.ai.AICon import net.horizonsend.ion.server.features.starship.control.movement.AIControlUtils import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace import org.bukkit.util.Vector import java.util.function.Supplier diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/FrigateCombatModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/FrigateCombatModule.kt index f209f4e606..b7709a7cae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/FrigateCombatModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/FrigateCombatModule.kt @@ -3,12 +3,12 @@ package net.horizonsend.ion.server.features.ai.module.combat import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getDirection +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import net.horizonsend.ion.server.miscellaneous.utils.getDirection import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace import java.util.function.Supplier class FrigateCombatModule(controller: AIController, private val toggleRandomTargeting: Boolean = true, targetingSupplier: Supplier) : CombatModule(controller, targetingSupplier) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/StarfighterCombatModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/StarfighterCombatModule.kt index fb4e1763f1..059865211b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/StarfighterCombatModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/StarfighterCombatModule.kt @@ -2,9 +2,9 @@ package net.horizonsend.ion.server.features.ai.module.combat import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getDirection -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getDirection +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import java.util.function.Supplier class StarfighterCombatModule(controller: AIController, targetingSupplier: Supplier) : CombatModule(controller, targetingSupplier) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/FleeModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/FleeModule.kt index 42abf34c67..72de10f993 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/FleeModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/FleeModule.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.ai.module.misc import net.horizonsend.ion.server.features.ai.module.targeting.TargetingModule import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import java.util.function.Supplier /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/CruiseModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/CruiseModule.kt index 7e0a10b178..1c0285e7d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/CruiseModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/CruiseModule.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.starship.control.controllers.ai.AICon import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import org.bukkit.Location import org.bukkit.block.BlockFace import java.util.function.Supplier @@ -21,11 +21,11 @@ import kotlin.math.abs * @param maximumCruiseDistanceSquared Does not cruise if the target is within this distance (squared). **/ class CruiseModule( - controller: AIController, - pathfindingModule: PathfindingModule, - val cruiseDestination: Supplier, - var shiftFlightType: ShiftFlightType, - var maximumCruiseDistanceSquared: Double = 90000.0, + controller: AIController, + pathfindingModule: PathfindingModule, + val cruiseDestination: Supplier, + var shiftFlightType: ShiftFlightType, + var maximumCruiseDistanceSquared: Double = 90000.0, ) : MovementModule(controller, pathfindingModule) { // The pathfinding controller will change the destination, so store the eventual destination in a seperate variable. var speedLimit = -1 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/MovementModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/MovementModule.kt index 3b4d9e9a2c..4e9f9d7ce3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/MovementModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/movement/MovementModule.kt @@ -5,8 +5,8 @@ import net.horizonsend.ion.server.features.starship.control.controllers.ai.AICon import net.horizonsend.ion.server.features.starship.control.movement.AIControlUtils import net.horizonsend.ion.server.features.starship.control.movement.StarshipCruising import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import org.bukkit.Location import org.bukkit.block.BlockFace import org.bukkit.util.Vector @@ -66,9 +66,9 @@ abstract class MovementModule( } open fun shiftFlyToVec3i( - origin: Location, - destination: Vec3i?, - stopCruising: Boolean = false + origin: Location, + destination: Vec3i?, + stopCruising: Boolean = false ) = Tasks.sync { val starship = controller.starship if (stopCruising) StarshipCruising.forceStopCruising(starship) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/PathfindingModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/PathfindingModule.kt index 249f7398a4..15670ee408 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/PathfindingModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/PathfindingModule.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.ai.module.pathfinding import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.util.Vector import java.util.function.Supplier diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/SteeringPathfindingModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/SteeringPathfindingModule.kt index ab95a514c8..1f0f0fd295 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/SteeringPathfindingModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/pathfinding/SteeringPathfindingModule.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.ai.module.pathfinding import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.average +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.average import org.bukkit.util.Vector import java.util.concurrent.LinkedBlockingDeque import java.util.function.Supplier diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/AxisStandoffPositioningModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/AxisStandoffPositioningModule.kt index 76c649d1e9..ac81c36cfd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/AxisStandoffPositioningModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/AxisStandoffPositioningModule.kt @@ -4,8 +4,8 @@ import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.ai.util.StarshipTarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.nearestPointToVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.nearestPointToVector import java.util.function.Supplier import kotlin.math.pow diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/BasicPositioningModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/BasicPositioningModule.kt index 5e19705da9..851becceab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/BasicPositioningModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/BasicPositioningModule.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.ai.module.positioning import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i class BasicPositioningModule(controller: AIController, private val goal: Vec3i) : PositioningModule(controller) { override fun findPosition(): Vec3i = goal diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/CirclingPositionModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/CirclingPositionModule.kt index 7f2ab82c40..aace6e5792 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/CirclingPositionModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/CirclingPositionModule.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.ai.module.positioning import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.control.movement.StarshipCruising -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import java.util.function.Supplier import kotlin.math.PI import kotlin.math.cos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/PositioningModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/PositioningModule.kt index 190ca25ec1..7d3dc141d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/PositioningModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/PositioningModule.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.ai.module.positioning import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i abstract class PositioningModule(controller: AIController) : net.horizonsend.ion.server.features.ai.module.AIModule(controller) { abstract fun findPosition(): Vec3i? diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/StandoffPositioningModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/StandoffPositioningModule.kt index 28f23bd715..f45a227670 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/StandoffPositioningModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/positioning/StandoffPositioningModule.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.ai.module.positioning import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.ai.util.StarshipTarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.util.Vector import java.util.function.Supplier import kotlin.math.pow diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt index df610429ea..256495a81c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt @@ -18,8 +18,8 @@ import net.horizonsend.ion.server.features.starship.control.controllers.Controll import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.modules.AISinkMessageFactory import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.getLocationNear import net.horizonsend.ion.server.miscellaneous.utils.placeSchematicEfficiently @@ -134,13 +134,13 @@ fun createFromClipboard( } private fun tryPilotWithController( - logger: Logger, - world: World, - origin: Vec3i, - type: StarshipType, - name: String, - createController: (ActiveControlledStarship) -> Controller, - callback: (ActiveControlledStarship) -> Unit = {} + logger: Logger, + world: World, + origin: Vec3i, + type: StarshipType, + name: String, + createController: (ActiveControlledStarship) -> Controller, + callback: (ActiveControlledStarship) -> Unit = {} ) { val (x, y, z) = origin val block = world.getBlockAt(x, y, z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/SpawningException.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/SpawningException.kt index 1b5d526951..234e6e81ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/SpawningException.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/SpawningException.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.ai.spawning import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World /** An exception relating to a cause of a failed spawn. */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/util/AITarget.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/util/AITarget.kt index 903c143fa9..00bf320c1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/util/AITarget.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/util/AITarget.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.ai.util import net.horizonsend.ion.server.features.starship.AutoTurretTargeting import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.add +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.add import org.bukkit.Location import org.bukkit.World import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt index f80b87c60c..4574061543 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFac import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.createItemDisplay import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.audience.Audience diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/blaster/BlasterProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/blaster/BlasterProjectile.kt index 5279b89232..fd98d8678d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/blaster/BlasterProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/blaster/BlasterProjectile.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.hasFlag import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.alongVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.alongVector import net.horizonsend.ion.server.miscellaneous.utils.get import net.kyori.adventure.key.Key.key import net.kyori.adventure.sound.Sound.Source diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/collectors/Collectors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/collectors/Collectors.kt index 30aca8fd02..1af790c921 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/collectors/Collectors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/collectors/Collectors.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.npcs.createNamedMemoryRegistry import net.horizonsend.ion.server.features.npcs.isCitizensLoaded import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.colorize -import net.horizonsend.ion.server.miscellaneous.utils.loadChunkAsync +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.loadChunkAsync import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.entity.EntityType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index 2d0508a56a..8fec01a170 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.isInRange +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isInRange import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.Bukkit import org.bukkit.Color diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt index 27c9e74b6c..b6aef21e2f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt @@ -8,8 +8,8 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.bukkitLocation +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import net.horizonsend.ion.server.miscellaneous.utils.toChunkLocal import org.bukkit.Bukkit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt index 9e36533d46..d51734a14b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.miscellaneous.utils.CHISELED_TYPES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/Shuttles.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/Shuttles.kt index e7c82d4c6d..07d8f39a23 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/Shuttles.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/Shuttles.kt @@ -16,12 +16,12 @@ import net.horizonsend.ion.server.features.nations.gui.openConfirmMenu import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.VAULT_ECO -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.action import net.horizonsend.ion.server.miscellaneous.utils.actionAndMsg import net.horizonsend.ion.server.miscellaneous.utils.colorize +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isInRange import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.isInRange import net.horizonsend.ion.server.miscellaneous.utils.msg import net.horizonsend.ion.server.miscellaneous.utils.placeSchematicEfficiently import net.horizonsend.ion.server.miscellaneous.utils.readSchematic diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/UnusedSoldShipPurge.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/UnusedSoldShipPurge.kt index 742302762b..57804441e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/UnusedSoldShipPurge.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/misc/UnusedSoldShipPurge.kt @@ -10,10 +10,10 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.control.controllers.NoOpController import net.horizonsend.ion.server.features.starship.destruction.StarshipDestruction import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld -import net.horizonsend.ion.server.miscellaneous.utils.chunkKeyX -import net.horizonsend.ion.server.miscellaneous.utils.chunkKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKeyZ import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.Chunk import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 0d4f09204e..3857bd5219 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -1,10 +1,11 @@ package net.horizonsend.ion.server.features.multiblock -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isValidYLevel import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.isValidYLevel import net.kyori.adventure.text.Component import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer @@ -13,7 +14,7 @@ import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.WallSign import org.bukkit.entity.Player abstract class Multiblock { @@ -23,7 +24,7 @@ abstract class Multiblock { open val requiredPermission: String? = null - open fun matchesSign(lines: Array): Boolean { + open fun matchesSign(lines: List): Boolean { for (i in 0..3) { if (signText[i] != null && signText[i] != lines[i]) { return false @@ -73,23 +74,25 @@ abstract class Multiblock { return shape.checkRequirements(originBlock, inward, loadChunks, particles) } + suspend fun signMatchesStructureAsync(sign: Sign, loadChunks: Boolean = true) = signMatchesStructureAsync(sign.location, loadChunks) + suspend fun signMatchesStructureAsync(signLocation: Location, loadChunks: Boolean = true) = + signMatchesStructureAsync(signLocation.world, Vec3i(signLocation), loadChunks) + suspend fun signMatchesStructureAsync( - signLocation: Location, - inward: BlockFace, + world: World, + origin: Vec3i, loadChunks: Boolean = true ): Boolean { - val world = signLocation.world + val block = world.getBlockAt(origin.x, origin.y, origin.z) + val sign = (getBukkitBlockState(block, loadChunks) as? Sign) ?: return false + val inward = sign.getFacing().oppositeFace - val x = signLocation.blockX + inward.modX - val y = signLocation.blockY + inward.modY - val z = signLocation.blockZ + inward.modZ + val x = origin.x + inward.modX + val y = origin.y + inward.modY + val z = origin.z + inward.modZ if (!isValidYLevel(y)) return false - val blockData: BlockData? = getBlockSnapshotAsync(world, x, y, z, loadChunks)?.data - - if (blockData !is org.bukkit.block.data.type.Sign) return false - return blockMatchesStructureAsync(world, Vec3i(x, y, z), inward, loadChunks) } @@ -132,4 +135,25 @@ abstract class Multiblock { } protected open fun onTransformSign(player: Player, sign: Sign) {} + + companion object { + fun getOrigin(sign: Sign): Vec3i { + val face = sign.getFacing() + + return Vec3i(sign.location).minus(Vec3i(face.modX, 0, face.modZ)) + } + + /** + * Gets a multiblock's origin from a possible sign + * + * Returns null if the provided block snapshot is not a sign + **/ + fun getOrigin(sign: BlockSnapshot): Vec3i? { + val data = sign.data as? WallSign ?: return null + + val face = data.facing + + return Vec3i(sign.x, sign.y, sign.z).minus(Vec3i(face.modX, 0, face.modZ)) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt index e595ab029c..1c95262101 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.util.awaitAllValues -import net.horizonsend.ion.server.features.multiblock.util.getBlockAsync import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BARGE_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUISER_REACTOR_CORE @@ -19,8 +18,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.CONCRETE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.MATERIALS import net.horizonsend.ion.server.miscellaneous.utils.STAINED_TERRACOTTA_TYPES import net.horizonsend.ion.server.miscellaneous.utils.TERRACOTTA_TYPES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.blockFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockData import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe @@ -235,13 +234,11 @@ class MultiblockShape { * TODO more documentation **/ suspend fun checkRequirementsSpecificAsync(world: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { - val (originX, originY, originZ) = origin - val blocks = getRequirementMap(inward).map { (offset, _) -> - val (x, y, z) = offset + val (x, y, z) = offset + origin - offset to getBlockAsync(world, originX + x, originY + y, originZ + z) - }.toMap().awaitAllValues() + offset to world.getBlockAt(x, y, z) + }.toMap() return getRequirementMap(inward).all { (offset, requirement) -> val block = blocks[offset]!! diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 9d2efb8609..cb3d81f1e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -5,8 +5,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.achievements.Achievement import net.horizonsend.ion.server.features.achievements.rewardAchievement @@ -145,28 +145,28 @@ import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.kyori.adventure.text.Component.newline -import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.event.ClickEvent -import net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN -import net.kyori.adventure.text.format.TextDecoration -import org.bukkit.Location +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.isSign +import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey +import org.bukkit.World import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.block.Action +import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.EquipmentSlot +import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import java.util.UUID object Multiblocks : IonServerComponent() { - private lateinit var multiblocks: List + private val multiblocks: MutableMap = mutableMapOf() private fun initMultiblocks() { - multiblocks = listOf( + multiblocks.putAll(listOf( CentrifugeMultiblock, CompressorMultiblock, FabricatorMultiblock, @@ -325,12 +325,15 @@ object Multiblocks : IonServerComponent() { BargeReactorMultiBlock, OdometerMultiblock, TestMultiblock - ) + ).associateBy { it.javaClass.simpleName }) } val context = CoroutineScope(Dispatchers.Default + SupervisorJob()) - private val multiblockCache: MutableMap = Object2ObjectOpenHashMap() + /** + * Map of world UUIDs to a map of block keys to Multiblock types + **/ + private val newMultiblockCache: MutableMap> = Object2ObjectOpenHashMap() override fun onEnable() { initMultiblocks() @@ -338,68 +341,87 @@ object Multiblocks : IonServerComponent() { log.info("Loaded ${multiblocks.size} multiblocks") } - fun all(): List = multiblocks + fun all(): List = multiblocks.values.toList() - @JvmStatic - @JvmOverloads - operator fun get(sign: Sign, checkStructure: Boolean = true, loadChunks: Boolean = true): Multiblock? { - val location: Location = sign.location - val pdc = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) + /** + * Get a multiblock from the sign + **/ + operator fun get(sign: Sign, checkStructure: Boolean = true, loadChunks: Boolean = false) = runBlocking { + getFromSignPosition(sign.world, sign.x, sign.y, sign.z, checkStructure, loadChunks) + } - val cached: Multiblock? = multiblockCache[location] - if (cached != null) { - val matchesSign = if (pdc != null) pdc == cached::class.simpleName else cached.matchesSign(sign.lines().toTypedArray()) + /** + * Get a multiblock from the sign position + **/ + operator fun get(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean = true, loadChunks: Boolean = false) = runBlocking { + getFromSignPosition(world, x, y, z, checkStructure, loadChunks) + } - // one was already cached before - if (matchesSign && (!checkStructure || cached.signMatchesStructure(sign, loadChunks = loadChunks))) { - if (pdc == null) { - sign.persistentDataContainer.set( - NamespacedKeys.MULTIBLOCK, - PersistentDataType.STRING, - cached::class.simpleName!! - ) - sign.update(false, false) - } + /** + * Get a multiblock by its identifying name + **/ + operator fun get(name: String) = multiblocks[name] - // it still matches so returned the cached one - return cached - } else { - // it no longer matches so remove it, and re-detect it afterwards - multiblockCache.remove(location) - } - } + /** + * Checks against the multiblock cache for a multiblock at a position + * + * Only considers detected multiblocks + **/ + suspend fun getFromSignPosition(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean, loadChunks: Boolean = false): Multiblock? { + val block = world.getBlockAt(x, y, z) + + val cached = checkCache(world, x, y, z, checkStructure, loadChunks) + + if (cached != null) return cached - for (multiblock in multiblocks) { - val matchesSign = - if (pdc != null) pdc == multiblock::class.simpleName else multiblock.matchesSign(sign.lines().toTypedArray()) - if (matchesSign && (!checkStructure || multiblock.signMatchesStructure(sign, loadChunks = loadChunks))) { - if (pdc == null) { + val sign = getBukkitBlockState(block, loadChunks) as? Sign ?: return null + + for ((name, multiblock) in multiblocks) { + if (!matchesPersistentDataContainer(sign.persistentDataContainer, multiblock)) { + if (!multiblock.matchesSign(sign.lines())) continue else Tasks.sync { sign.persistentDataContainer.set( NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, - multiblock::class.simpleName!! + name ) + sign.isWaxed = true sign.update(false, false) } - - if (checkStructure) { - multiblockCache[location] = multiblock - } - return multiblock } + + if (!multiblock.signMatchesStructureAsync(world, Vec3i(x, y, z), loadChunks)) continue; + + return multiblock } - return null + return null; + } + + /** + * Checks against the multiblock cache for a multiblock at a position + **/ + private suspend fun checkCache(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean, loadChunks: Boolean): Multiblock? { + val worldCache = newMultiblockCache[world.uid] ?: return null + + val key = toBlockKey(x, y, z) + + val possibleMultiblock = worldCache[key] ?: return null + + if (checkStructure && !possibleMultiblock.signMatchesStructureAsync(world, Vec3i(x, y, z), loadChunks)) return null + + return possibleMultiblock } fun getFromPDC(sign: Sign): Multiblock? { val pdc = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return null - return multiblocks.firstOrNull { it::class.simpleName == pdc } + return multiblocks[pdc] } - fun matchesPersistentDataContainer(sign: Sign, multiblock: Multiblock): Boolean { - return sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) == multiblock::class.simpleName + fun matchesPersistentDataContainer(persistentDataContainer: PersistentDataContainer, multiblock: Multiblock): Boolean { + val value = persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return false + + return value == multiblock::class.simpleName } /** @@ -427,7 +449,7 @@ object Multiblocks : IonServerComponent() { } // Check all multiblocks - for (multiblock in multiblocks) { + for ((_, multiblock) in multiblocks) { // If it has the same sign text as the multiblock if (multiblock.matchesUndetectedSign(sign)) { // And is built properly @@ -439,29 +461,7 @@ object Multiblocks : IonServerComponent() { } // Update everything that needs to be done sync - Tasks.sync { - event.player.rewardAchievement(Achievement.DETECT_MULTIBLOCK) - - multiblock.setupSign(player, sign) - - val (x, y, z) = Vec3i(sign.location).minus(Vec3i(sign.getFacing().modX, 0, sign.getFacing().modZ)) - - val chunkX = x.shr(4) - val chunkZ = z.shr(4) - - val chunk = event.player.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - - chunk.addMultiblock(multiblock, x, y, z) - - sign.persistentDataContainer.set( - NamespacedKeys.MULTIBLOCK, - PersistentDataType.STRING, - multiblock::class.simpleName!! // Shouldn't be any anonymous multiblocks - ) - - sign.isWaxed = true - sign.update() - } + createNewMultiblock(multiblock, sign, event.player) return@launch } else { @@ -479,28 +479,65 @@ object Multiblocks : IonServerComponent() { } } - private fun setupCommand(player: Player, sign: Sign, lastMatch: Multiblock) { - val multiblockType = lastMatch.name + @EventHandler + fun onPlayerBreakBlock(event: BlockBreakEvent) = context.launch { + val player = event.player + if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return@launch + + val sign = getBukkitBlockState(event.block, false) as? Sign ?: return@launch + + val multiblock = getFromSignPosition( + sign.world, + sign.x, + sign.y, + sign.z, + checkStructure = true, + loadChunks = false + ) ?: return@launch + + removeMultiblock(multiblock, sign, player) + } - val possibleTiers = multiblocks.filter { it.name == multiblockType } + /** + * Called upon the creation of a new multiblock + * + * Handles the sign, registration + **/ + fun createNewMultiblock(multiblock: Multiblock, sign: Sign, detector: Player) = Tasks.sync { + detector.rewardAchievement(Achievement.DETECT_MULTIBLOCK) - val message = text() - .append(text("Which type of $multiblockType are you trying to build? (Click one)")) - .append(newline()) + multiblock.setupSign(detector, sign) - for (tier in possibleTiers) { - val tierName = tier.javaClass.simpleName + val (x, y, z) = Multiblock.getOrigin(sign) - val command = "/multiblock check $tierName ${sign.x} ${sign.y} ${sign.z}" + val chunkX = x.shr(4) + val chunkZ = z.shr(4) - val tierText = bracketed(text(tierName, DARK_GREEN, TextDecoration.BOLD)) - .clickEvent(ClickEvent.runCommand(command)) - .hoverEvent(text(command).asHoverEvent()) + val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - message.append(tierText) - if (possibleTiers.indexOf(tier) != possibleTiers.size - 1) message.append(text(", ")) + sign.persistentDataContainer.set( + NamespacedKeys.MULTIBLOCK, + PersistentDataType.STRING, + multiblock::class.simpleName!! // Shouldn't be any anonymous multiblocks + ) + + sign.isWaxed = true + + Tasks.sync { + sign.update() } - player.sendMessage(message.build()) + chunk.addMultiblock(multiblock, sign) + } + + fun removeMultiblock(multiblock: Multiblock, sign: Sign, player: Player) = Tasks.sync { + val (x, y, z) = Multiblock.getOrigin(sign) + + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync + + chunk.removeMultiblock(x, y, z) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index acbd1eef5b..52a0c40ed8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,9 +1,12 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Location import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign /** * @param x The absolute x position of this multiblock's origin location @@ -19,7 +22,8 @@ abstract class MultiblockEntity( val y: Int, val z: Int, val world: World, - val type: Multiblock + val type: Multiblock, + val signOffset: BlockFace ) { /** * Returns the origin of this multiblock as a Location @@ -44,9 +48,24 @@ abstract class MultiblockEntity( * This data is serialized and stored on the chunk when not loaded. **/ fun store(): PersistentMultiblockData { - val store = PersistentMultiblockData(x, y, z, type) + val store = PersistentMultiblockData(x, y, z, type, signOffset) storeAdditionalData(store) return store } + + /** + * Gets the sign of this multiblock + **/ + suspend fun getSign(): Sign? { + val signLoc = Vec3i(x, y, z) + Vec3i(signOffset.modX, 0, signOffset.modZ) + + return getBukkitBlockState(world.getBlockAt(signLoc.x, signLoc.y, signLoc.z), loadChunks = false) as? Sign + } + + suspend fun isIntact(): Boolean { + val sign = getSign() ?: return false + + return type.signMatchesStructureAsync(sign) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index ec2d499ee9..833c616ec9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -5,10 +5,12 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ADDITIONAL_MULTIBLOCK_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_SIGN_OFFSET import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z import org.bukkit.NamespacedKey +import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry import org.bukkit.persistence.PersistentDataAdapterContext @@ -18,8 +20,8 @@ import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.STRING import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER -class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Multiblock) { - constructor(x: Int, y: Int, z: Int, type: Multiblock, additionalData: PersistentDataContainer) : this(x, y, z, type) { +class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Multiblock, val signOffset: BlockFace) { + constructor(x: Int, y: Int, z: Int, type: Multiblock, signOffset: BlockFace, additionalData: PersistentDataContainer) : this(x, y, z, type, signOffset) { this.additionalData = additionalData } @@ -38,6 +40,7 @@ class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Mul pdc.set(X, INTEGER, complex.x) pdc.set(Y, INTEGER, complex.y) pdc.set(Z, INTEGER, complex.z) + pdc.set(MULTIBLOCK_SIGN_OFFSET, STRING, complex.signOffset.toString()) pdc.set(MULTIBLOCK, STRING, complex.type::class.java.simpleName) @@ -46,16 +49,21 @@ class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Mul return pdc } - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): PersistentMultiblockData = runCatching { + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): PersistentMultiblockData = try { val x = primitive.get(X, INTEGER)!! val y = primitive.get(Y, INTEGER)!! val z = primitive.get(Z, INTEGER)!! + val signDirectionString = primitive.get(MULTIBLOCK_SIGN_OFFSET, STRING)!! + val signDirection = BlockFace.valueOf(signDirectionString) val multiblockType = Multiblocks.all().firstOrNull { it::class.simpleName == primitive.get(MULTIBLOCK, STRING) }!! val additionalData = primitive.get(ADDITIONAL_MULTIBLOCK_DATA, TAG_CONTAINER)!! - return@runCatching PersistentMultiblockData(x, y, z, multiblockType, additionalData) - }.getOrNull() ?: throw SerializationException("Error deserializing multiblock data!") + PersistentMultiblockData(x, y, z, multiblockType, signDirection, additionalData) + } catch (e: Throwable) { + e.printStackTrace() + throw SerializationException("Error deserializing multiblock data!") + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt index 5d601d5b8d..cc19528bb8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultibloc import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign abstract class PoweredMultiblockEntity( @@ -13,8 +14,9 @@ abstract class PoweredMultiblockEntity( z: Int, world: World, type: Multiblock, + signOffset: BlockFace, private var power: Int -) : MultiblockEntity(x, y, z, world, type) { +) : MultiblockEntity(x, y, z, world, type, signOffset) { init { require(type is PowerStoringMultiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/TickingMultiblockEntity.kt similarity index 63% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/TickingMultiblockEntity.kt index f8f7f53b13..4b4c09b625 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/TickingMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/TickingMultiblockEntity.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.multiblock.type +package net.horizonsend.ion.server.features.multiblock.entity /** * Any multiblock that should be ticked along with the world **/ -interface TickingMultiblock { +interface TickingMultiblockEntity { /** * Whether the tick should be run async **/ @@ -12,5 +12,5 @@ interface TickingMultiblock { /** * The logic that is run upon world tick **/ - fun tick() + suspend fun tick() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt index f284bf9a85..ff9dc19a33 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt @@ -1,9 +1,49 @@ package net.horizonsend.ion.server.features.multiblock.type +import kotlinx.coroutines.launch +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState +import net.horizonsend.ion.server.listener.SLEventListener import org.bukkit.block.Sign import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.EquipmentSlot interface InteractableMultiblock { fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) + + companion object : SLEventListener() { + @EventHandler + fun onPlayerInteract(event: PlayerInteractEvent) = Multiblocks.context.launch { + if (event.hand != EquipmentSlot.HAND) return@launch + if (event.action != Action.RIGHT_CLICK_BLOCK) return@launch + val player = event.player + + val clickedBlock = event.clickedBlock ?: return@launch + val sign = getBukkitBlockState(clickedBlock, false) as? Sign ?: return@launch + + val multiblock = Multiblocks.getFromSignPosition( + sign.world, + sign.x, + sign.y, + sign.z, + checkStructure = true, + loadChunks = false + ) + + if (multiblock !is InteractableMultiblock) return@launch + + multiblock.requiredPermission?.let { permission -> + if (!player.hasPermission(permission)) { + player.userError("You don't have permission to use that multiblock!") + return@launch + } + } + + multiblock.onSignInteract(sign, player, event) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt index 2d521dd451..24b531459f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getSphereBlocks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks import org.bukkit.ChatColor import org.bukkit.Material import org.bukkit.Particle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt index 6ea11202fe..c1ebfbac61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt @@ -14,7 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.type.defense.projectile.An import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.RotatingMultiblock import net.horizonsend.ion.server.features.starship.control.movement.PlayerStarshipControl import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt index e7bf49c90c..706b4df975 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isDoor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt index 04209af053..f042afb0bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isDoor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt index 887d1d1363..f255f44d25 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.multiblock.type.dockingtube import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.kyori.adventure.text.minimessage.MiniMessage diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt index c863261af9..d2e1d5d86e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.farming import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index bfc74dfb48..84f35d4b57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.multiblock.type.farming.CropMultiblock import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index fec31a1e05..c54c4b99c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.multiblock.type.farming.CropMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt index 0cf2befae1..11b8943e89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt index f49abedce0..18a08faaef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt @@ -5,8 +5,8 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.add +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.add import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt index 99a9bcbab1..f23bf7c0fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass1 : HyperdriveMultiblock() { override val maxPower = 30_000 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt index b38867408d..fa792de45d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass2 : HyperdriveMultiblock() { override val maxPower = 50_000 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt index 063b90e7eb..1d24aa53a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass3 : HyperdriveMultiblock() { override val maxPower = 75_000 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt index 0543cf26a4..555417574e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass4 : HyperdriveMultiblock() { override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt index 6fe77923ed..5fddb6e4ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.Subsys import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.MiningLaserSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt index 08a24e4b1f..719e7b9d71 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.mininglasers import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt index 144ec7cf37..13e8656b45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.mininglasers import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt index 9233ed1a19..68ce7439c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.mininglasers import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt index 538a93c03e..7b7ab691b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.mininglasers import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt index c0fb8dbd0e..b580a8ddb1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt index 57547e0abd..e56f15401b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SPLITTER_DIRECTION -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getStateSafe import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt index b52e5e58c4..90efa77991 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.LandingGearSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.block.BlockFace @@ -16,7 +16,7 @@ object LandingGearMultiblock : Multiblock(), SubsystemMultiblock): Boolean { + override fun matchesSign(lines: List): Boolean { return false } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt index 4378bc7d7b..b49faa5075 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.Subsys import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.OdometerSubsystem import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.AQUA diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 7948812148..0f07044088 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -1,21 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.type.misc +import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.common.utils.text.plainText +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextDecoration +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer import org.bukkit.Material import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent @@ -35,8 +38,15 @@ object TestMultiblock : Multiblock(), EntityMultiblock): Boolean { - val modified = lines.clone() + override fun matchesSign(lines: List): Boolean { + val modified = lines.toMutableList() modified[1] = signText[1]!! return super.matchesSign(modified) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt index c4727f9e7a..169c9b8dbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getSphereBlocks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks import org.bukkit.block.Sign abstract class SphereShieldMultiblock : ShieldMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt index 1fac7c14fc..7198a51ca5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.World +import org.bukkit.block.BlockFace /** * A multiblock which has a corresponding multiblock entity @@ -14,7 +15,7 @@ interface EntityMultiblock { /** * Create the multiblock entity using the stored data **/ - fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int): T + fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): T fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): T? { val chunkX = x.shr(4) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt index 2cc81d3c9f..f2d41b7b7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt @@ -11,7 +11,7 @@ abstract class SignlessStarshipWeaponMultiblock : override val name: String = javaClass.simpleName - override fun matchesSign(lines: Array): Boolean { + override fun matchesSign(lines: List): Boolean { return false } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt index bde9b5d5d8..3dd91dfe03 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace interface SubsystemMultiblock { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt index 3d07e77b49..ebd0ac2fae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LaserCannonWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace object LaserCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt index 19ba29f482..041fff1bd4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PlasmaCannonWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace object PlasmaCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt index 94be6ed426..5a8bb3d783 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PulseCannonWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace object PulseCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt index 1c95f8fc5a..260a8b58d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.CapitalBeamWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace object CapitalBeamStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt index 8c4e2829d6..064753381b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.CthulhuBeamSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace sealed class CthulhuBeamMutliblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt index ce7f4b2d07..8aa656fb3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.FlamethrowerWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt index 2ccfdf29bb..71cff08dfa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.MiniPhaserWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt index b93e4f3873..5d124ef302 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.PumpkinCannonWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt index ca66995461..2be9785e6e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.SonicMissileWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt index 340602a4ca..19638bae72 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.AIHeavyLaserWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt index 4c337ce26d..f40e843ad1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.ArsenalRocketStarshipWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace sealed class ArsenalRocketStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt index db9367b148..0ccef35a0f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.HeavyLaserWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace object HeavyLaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt index 06d7c5ea64..04b7163dbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.PhaserWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt index 6dbd295e7a..b10837ce4b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.RocketWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace sealed class RocketStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt index 0b27782116..45a51f7fde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TorpedoWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace object TorpedoStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt index de1a0f1c25..12bf97b4f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PointDefenseSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace sealed class PointDefenseStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt index 420acb7aec..4b512ccddf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.HeavyTurretWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt index 7691708ea6..d2de379a4f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.IonTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.IonTurretProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material.END_ROD import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt index 41250f367c..57a2f8219b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LightTurretWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material.GRINDSTONE import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt index 55cd800ab7..dc120e31f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.QuadTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.QuadTurretProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt index 2c6f61e133..db1f4b3396 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt @@ -5,8 +5,8 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rightFace @@ -32,11 +32,11 @@ abstract class RotatingMultiblock : Multiblock() { } fun rotate( - origin: Vec3i, - world: World, - oldFace: BlockFace, - newFace: BlockFace, - callback: (sign: Vec3i, oldKeys: LongOpenHashSet, newKeys: LongOpenHashSet, newFace: BlockFace) -> Unit = { _, _, _, _ -> } + origin: Vec3i, + world: World, + oldFace: BlockFace, + newFace: BlockFace, + callback: (sign: Vec3i, oldKeys: LongOpenHashSet, newKeys: LongOpenHashSet, newFace: BlockFace) -> Unit = { _, _, _, _ -> } ): BlockFace { val i = when (newFace) { oldFace -> return oldFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt index eec75e416e..5ba3778ae0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TriTurretWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt index d216b1140e..1f3e4791bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt @@ -12,8 +12,8 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.TurretLaserProjectile import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index e4b4aea6de..dce5db897a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -6,9 +6,8 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred import kotlinx.coroutines.future.asDeferred import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot -import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.loadChunkAsync import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.loadChunkAsync import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.core.BlockPos import net.minecraft.server.level.ServerLevel @@ -43,16 +42,6 @@ suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChun return getChunkSnapshotAsync(world, x, z, loadChunks)?.getBlockSnapshot(x, y, z) } -fun getBlockAsync(world: World, x: Int, y: Int, z: Int): Deferred { - val deferred = CompletableDeferred() - - Tasks.async { - deferred.complete(world.getBlockAt(x, y, z)) - } - - return deferred -} - suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } suspend fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt index 6113954fce..d835b27a21 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt @@ -11,8 +11,11 @@ class BlockSnapshot(val x: Int, val y: Int, val z: Int, val type: Material, val if (x shr 4 != getX()) return null if (z shr 4 != getZ()) return null - val localX = x % 16 - val localZ = z % 16 + val chunkOriginX = getX().shl(4) + val chunkOriginZ = getZ().shl(4) + + val localX = x - chunkOriginX + val localZ = z - chunkOriginZ return BlockSnapshot(x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionCapturableStation.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionCapturableStation.kt index b95907f81e..e0c29ab588 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionCapturableStation.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionCapturableStation.kt @@ -19,7 +19,7 @@ import net.horizonsend.ion.common.utils.miscellaneous.squared import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.nations.NATIONS_BALANCE import net.horizonsend.ion.server.features.nations.NationsMap -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import org.bukkit.entity.Player import java.time.DayOfWeek diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSettlementZone.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSettlementZone.kt index 7470391e2f..88b60fb1e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSettlementZone.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSettlementZone.kt @@ -24,7 +24,7 @@ import net.horizonsend.ion.server.command.nations.settlementZones.SettlementZone import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.nations.region.Regions import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import org.bukkit.Location import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSpaceStation.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSpaceStation.kt index 94150bd7db..950b36714a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSpaceStation.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSpaceStation.kt @@ -26,7 +26,7 @@ import net.horizonsend.ion.server.features.space.spacestations.CachedNationSpace import net.horizonsend.ion.server.features.space.spacestations.CachedPlayerSpaceStation import net.horizonsend.ion.server.features.space.spacestations.CachedSettlementSpaceStation import net.horizonsend.ion.server.features.space.spacestations.SpaceStationCache -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import org.bukkit.entity.Player import org.litote.kmongo.Id diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/NPCManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/NPCManager.kt index 4eac15beb9..71a1837d27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/NPCManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/NPCManager.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.npcs import net.citizensnpcs.api.CitizensAPI import net.citizensnpcs.api.npc.NPC import net.citizensnpcs.api.npc.NPCRegistry -import net.horizonsend.ion.server.miscellaneous.utils.loadChunkAsync +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.loadChunkAsync import org.bukkit.Location import org.bukkit.entity.Entity import org.bukkit.entity.EntityType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt index 968ade164f..3179eff1e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/npcs/StarshipDealers.kt @@ -18,7 +18,7 @@ import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtect import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement import net.horizonsend.ion.server.miscellaneous.utils.MenuHelper -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getMoneyBalance import net.horizonsend.ion.server.miscellaneous.utils.hasEnoughMoney import net.horizonsend.ion.server.miscellaneous.utils.placeSchematicEfficiently diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/player/DutyModeMonitor.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/player/DutyModeMonitor.kt index 37d7e4415d..24bb8c1007 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/player/DutyModeMonitor.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/player/DutyModeMonitor.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.starship.control.controllers.player.PlayerController import net.horizonsend.ion.server.features.starship.event.StarshipPilotedEvent import net.horizonsend.ion.server.features.starship.event.StarshipUnpilotEvent -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.listen import org.bukkit.entity.Player import org.bukkit.event.inventory.InventoryClickEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/sidebar/command/BookmarkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/sidebar/command/BookmarkCommand.kt index ff035e4af2..3341696d2a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/sidebar/command/BookmarkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/sidebar/command/BookmarkCommand.kt @@ -17,7 +17,7 @@ import net.horizonsend.ion.common.utils.text.lineBreakWithCenterText import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor.WHITE diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt index 8cb609e945..e4922418dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt @@ -15,6 +15,8 @@ import net.horizonsend.ion.server.features.space.body.CachedStar import net.horizonsend.ion.server.features.space.body.planet.CachedOrbitingPlanet import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet import net.horizonsend.ion.server.features.space.body.planet.CachedRoguePlanet +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedStar.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedStar.kt index 068eb83912..78a6d13c81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedStar.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedStar.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.space.body import net.horizonsend.ion.common.database.Oid import net.horizonsend.ion.common.database.schema.space.Star import net.horizonsend.ion.common.utils.miscellaneous.d -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getSphereBlocks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks import net.horizonsend.ion.server.miscellaneous.utils.nms import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.state.BlockState diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CelestialBody.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CelestialBody.kt index fed3d290a9..3af1e62834 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CelestialBody.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CelestialBody.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.space.body import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement.placeImmediate +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.state.BlockState import org.bukkit.Bukkit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt index b2ea55058c..f5c0a43050 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.space.data import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.BLOCKS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.PALETTE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y -import net.horizonsend.ion.server.miscellaneous.utils.component1 -import net.horizonsend.ion.server.miscellaneous.utils.component2 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component1 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component2 import net.minecraft.core.BlockPos import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.chunk.LevelChunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt index e41f24fe72..6a9d09da3d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/BridgeOfDeath.kt @@ -9,8 +9,8 @@ import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.validator. import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED import net.horizonsend.ion.server.miscellaneous.utils.Notify -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.castSpawnEntity +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.minecraft.nbt.CompoundTag diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt index 39747769ca..88a6735704 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CoolantLeak.kt @@ -12,10 +12,10 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints import net.horizonsend.ion.server.miscellaneous.utils.runnable -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints +import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.nbt.CompoundTag import org.bukkit.Material import org.bukkit.Particle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt index 56dbed8714..26d6b9fd09 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/CowTipper.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints import net.horizonsend.ion.server.miscellaneous.utils.runnable -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import net.minecraft.nbt.CompoundTag diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt index 8deaf3917e..3060dbba41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseBots.kt @@ -6,9 +6,9 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.castSpawnEntity -import net.horizonsend.ion.server.miscellaneous.utils.toBlockPos +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockPos import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updateLore import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt index 2e78130125..61c7b4a5ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefenseMatrix.kt @@ -4,9 +4,9 @@ import fr.skytasul.guardianbeam.Laser import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.castSpawnEntity -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.horizonsend.ion.server.miscellaneous.utils.runnable import net.minecraft.nbt.CompoundTag import org.bukkit.FluidCollisionMode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt index 9728ac47a1..0841289def 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/DefuseBomb.kt @@ -6,14 +6,14 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LOCKED -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.runnable -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints import net.minecraft.nbt.CompoundTag import org.bukkit.Material import org.bukkit.Sound diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt index 8f4ad33bcc..412bc80ee7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/Encounters.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.space.encounters import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ENCOUNTER import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.INACTIVE -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.minecraft.nbt.CompoundTag import org.bukkit.NamespacedKey import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt index 65c481b077..94c60ba33c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/encounters/TimedBomb.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.space.encounters import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints import net.horizonsend.ion.server.miscellaneous.utils.runnable -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints import net.minecraft.nbt.CompoundTag import org.bukkit.Sound import org.bukkit.block.Chest diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/AutoTurretTargeting.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/AutoTurretTargeting.kt index 3d4d34adcc..df0ed5be00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/AutoTurretTargeting.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/AutoTurretTargeting.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.entity.EntityType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt index 415d00f0ff..bd7e220eb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt @@ -17,8 +17,8 @@ import net.horizonsend.ion.server.features.starship.active.ActiveControlledStars import net.horizonsend.ion.server.features.starship.active.ActiveStarshipFactory import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.blockKey import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.listen import net.kyori.adventure.audience.Audience import org.bukkit.Bukkit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedShipWorldCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedShipWorldCache.kt index b0adb71f51..2b7353fdec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedShipWorldCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedShipWorldCache.kt @@ -7,10 +7,10 @@ import com.google.common.collect.HashMultimap import com.google.common.collect.Multimap import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.common.database.schema.starships.StarshipData -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld -import net.horizonsend.ion.server.miscellaneous.utils.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey import net.horizonsend.ion.server.miscellaneous.utils.orNull import org.bukkit.Chunk import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Hangars.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Hangars.kt index 79fade2470..b3e25f2ffd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Hangars.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Hangars.kt @@ -6,10 +6,10 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.miscellaneous.utils.PerWorld import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe import net.horizonsend.ion.server.miscellaneous.utils.listen import net.horizonsend.ion.server.miscellaneous.utils.nms diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt index 6450699e6d..6a7bd53627 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt @@ -43,12 +43,12 @@ import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShi import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.actualType -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.createData import net.horizonsend.ion.server.miscellaneous.utils.isPilot import net.horizonsend.ion.server.miscellaneous.utils.listen diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index e4bd0a642f..20e4c64d85 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -66,12 +66,12 @@ import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.actualType -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.leftFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt index 0785eb005d..e0c73282d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt @@ -6,14 +6,14 @@ import net.horizonsend.ion.common.database.schema.starships.StarshipData import net.horizonsend.ion.common.utils.text.miniMessage import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.actualType -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld -import net.horizonsend.ion.server.miscellaneous.utils.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.isConcrete import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipSchematic.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipSchematic.kt index 81c5fe3fe3..df8e6f5470 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipSchematic.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipSchematic.kt @@ -10,7 +10,7 @@ import com.sk89q.worldedit.math.BlockVector3 import com.sk89q.worldedit.regions.CuboidRegion import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipState.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipState.kt index 8c25d2e7cf..27c3461777 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipState.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipState.kt @@ -11,12 +11,12 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ -import net.horizonsend.ion.server.miscellaneous.utils.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey import net.horizonsend.ion.server.miscellaneous.utils.toBukkitBlockData import org.bukkit.World import org.bukkit.block.data.BlockData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt index 45fbce54c3..986493e644 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt @@ -8,10 +8,10 @@ import net.horizonsend.ion.common.utils.miscellaneous.ComponentMessageException import net.horizonsend.ion.server.features.starship.Mass import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.kyori.adventure.audience.Audience import net.starlegacy.feature.starship.active.ActiveStarshipHitbox import org.bukkit.Bukkit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt index dc622eadc5..66fb13ecfd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt @@ -23,7 +23,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.StarshipWea import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AutoWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Bukkit.getPluginManager import org.bukkit.entity.Entity import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarships.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarships.kt index b488112c29..bcfb15f01c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarships.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarships.kt @@ -18,9 +18,9 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.hasFlag import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/StarshipDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/StarshipDisplay.kt index 40a73cd949..5700bbba0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/StarshipDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/StarshipDisplay.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.starship.control.controllers.player.P import net.horizonsend.ion.server.features.starship.hyperspace.Hyperspace import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceMovement import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.registerIcon import net.kyori.adventure.text.format.TextColor import org.bukkit.Bukkit @@ -196,12 +196,12 @@ object StarshipDisplay : IonServerComponent(true) { /** Store the location, icon, and other details of a starship on the map */ data class StarshipIcon( - val charIdentifier: String, - val displayName: String, - val icon: MarkerIcon, - val world: World, - var position: Vec3i, - val description: String, + val charIdentifier: String, + val displayName: String, + val icon: MarkerIcon, + val world: World, + var position: Vec3i, + val description: String, val circles: List ) { fun update(markerSet: MarkerSet) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index b650524ac9..516eb4f544 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock @@ -43,7 +44,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.thruster.ThrusterT import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isFroglight import net.horizonsend.ion.server.miscellaneous.utils.isWallSign @@ -133,7 +134,7 @@ object SubsystemDetector { private fun detectSign(starship: ActiveControlledStarship, block: Block) { val sign = block.state as Sign - if (Multiblocks.getFromPDC(sign) is net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield) { + if (Multiblocks.getFromPDC(sign) is AreaShield) { throw ActiveStarshipFactory.StarshipActivationException("Starships cannot fly with area shields!") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/Controller.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/Controller.kt index a30a929da5..5b4921eb2f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/Controller.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/Controller.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.audience.Audience import net.kyori.adventure.audience.ForwardingAudience import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/ai/AIController.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/ai/AIController.kt index aa15a11f0a..bbd9a72914 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/ai/AIController.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/ai/AIController.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.starship.control.controllers.Controll import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.sortedByValue import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/AIControlUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/AIControlUtils.kt index 13dd366b94..6f292b7bd8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/AIControlUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/AIControlUtils.kt @@ -6,11 +6,11 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.control.weaponry.StarshipWeaponry import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToPitchYaw import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace -import net.horizonsend.ion.server.miscellaneous.utils.vectorToPitchYaw import org.bukkit.Location import org.bukkit.block.BlockFace import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/StarshipControl.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/StarshipControl.kt index c7c4fa61ed..03c79b3a6e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/StarshipControl.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/movement/StarshipControl.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCoold import net.horizonsend.ion.server.features.starship.movement.StarshipTeleportation import net.horizonsend.ion.server.features.starship.movement.TranslateMovement import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/destruction/StandardSinkProvider.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/destruction/StandardSinkProvider.kt index 4d7acfa929..1e171acc15 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/destruction/StandardSinkProvider.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/destruction/StandardSinkProvider.kt @@ -11,13 +11,13 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.hasFlag import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.isBlockLoaded import net.horizonsend.ion.server.miscellaneous.utils.nms import net.minecraft.world.level.block.state.BlockState diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt index 1f6df6ae3c..3076c599f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt @@ -16,8 +16,8 @@ import net.horizonsend.ion.server.features.economy.bazaar.Merchants import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.blockKey import net.horizonsend.ion.server.miscellaneous.utils.canAccess +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getMoneyBalance import net.horizonsend.ion.server.miscellaneous.utils.isSign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt index f700d6b5f1..ea778f2eff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt @@ -4,10 +4,10 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.setNMSBlockData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/HyperspaceMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/HyperspaceMovement.kt index 4d583f1c5a..80e1b76115 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/HyperspaceMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/HyperspaceMovement.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.progression.achievements.rewardAchiev import net.horizonsend.ion.server.features.starship.PilotedStarships.isPiloted import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import org.bukkit.Location import org.bukkit.Particle import org.bukkit.Vibration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/MassShadows.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/MassShadows.kt index 22be4fe893..2c8431210b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/MassShadows.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/hyperspace/MassShadows.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.Interdiction import net.horizonsend.ion.server.features.starship.PilotedStarships.getDisplayName import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/OptimizedMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/OptimizedMovement.kt index fb404a3203..4f8d737105 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/OptimizedMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/OptimizedMovement.kt @@ -4,13 +4,13 @@ import net.horizonsend.ion.server.features.starship.Hangars import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ -import net.horizonsend.ion.server.miscellaneous.utils.chunkKey -import net.horizonsend.ion.server.miscellaneous.utils.chunkKeyX -import net.horizonsend.ion.server.miscellaneous.utils.chunkKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKeyZ import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.nms import net.minecraft.core.BlockPos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt index cc4391e443..f33e17f41b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt @@ -26,11 +26,11 @@ import net.horizonsend.ion.server.features.starship.subsystem.misc.CryopodSubsys import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.listener.misc.ProtectionListener -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rectangle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovementException.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovementException.kt index c8bedee75b..d471d08346 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovementException.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovementException.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.common.utils.miscellaneous.ComponentMessageException import net.horizonsend.ion.common.utils.text.colors.HEColorScheme import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.common.utils.text.toComponent -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipTeleportation.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipTeleportation.kt index bb825178f1..20e44e3103 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipTeleportation.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipTeleportation.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.utils.miscellaneous.d import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.control.movement.StarshipCruising -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Location import org.bukkit.World import java.util.concurrent.CompletableFuture diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt index 5b8fd0b7c8..50ca2a4797 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.movement import io.papermc.paper.entity.TeleportFlag import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.add +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.add import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.world.entity.Relative import net.minecraft.world.level.block.state.BlockState diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/AbstractMultiblockSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/AbstractMultiblockSubsystem.kt index c3946b5459..a144d3f535 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/AbstractMultiblockSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/AbstractMultiblockSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/StarshipSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/StarshipSubsystem.kt index 3b7488ebc4..473b83ab3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/StarshipSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/StarshipSubsystem.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.subsystem import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i abstract class StarshipSubsystem(open val starship: ActiveStarship, var pos: Vec3i) { /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/LandingGearSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/LandingGearSubsystem.kt index cedeb29824..9972489237 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/LandingGearSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/LandingGearSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.misc import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.data.type.Observer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt index 0c0b4a0249..f847811dc8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt @@ -20,7 +20,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsy import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.enumSetOf import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.horizonsend.ion.server.miscellaneous.utils.runnable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt index d6a2ad3c62..563f942568 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/OdometerSubsystem.kt @@ -12,8 +12,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsyst import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/BoxShieldSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/BoxShieldSubsystem.kt index 167bbf4735..061a62414c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/BoxShieldSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/BoxShieldSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.shield import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.block.Block diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/SphereShieldSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/SphereShieldSubsystem.kt index d8280b7734..3c19903238 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/SphereShieldSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/SphereShieldSubsystem.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.shield import net.horizonsend.ion.common.utils.miscellaneous.squared import net.horizonsend.ion.server.features.multiblock.type.particleshield.SphereShieldMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import org.bukkit.block.Block import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/StarshipShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/StarshipShields.kt index 0c9095bba0..b58a849adc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/StarshipShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/shield/StarshipShields.kt @@ -13,11 +13,11 @@ import net.horizonsend.ion.server.listener.misc.ProtectionListener import net.horizonsend.ion.server.miscellaneous.utils.PerWorld import net.horizonsend.ion.server.miscellaneous.utils.SLTextStyle import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.nms import net.minecraft.core.BlockPos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterSubsystem.kt index 4cb26f1396..0ed89f2490 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterSubsystem.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.thruster import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace /** thruster subsystem representing a single thruster, the facing direction being forward */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/CannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/CannonWeaponSubsystem.kt index 485b145b7a..e966ec7531 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/CannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/CannonWeaponSubsystem.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Location import org.bukkit.block.BlockFace import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TargetTrackingCannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TargetTrackingCannonWeaponSubsystem.kt index 6db458d7a3..c58d1c559a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TargetTrackingCannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TargetTrackingCannonWeaponSubsystem.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt index 1a510b8b28..6e30643621 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt @@ -5,8 +5,8 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/WeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/WeaponSubsystem.kt index 7589d0501d..f545634014 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/WeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/WeaponSubsystem.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.BalancingSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.util.Vector import java.util.concurrent.TimeUnit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt index c70ae227be..cbddd88bf3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt @@ -9,15 +9,15 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.proje import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.util.Vector import java.util.concurrent.TimeUnit class CapitalBeamWeaponSubsystem( - starship: ActiveStarship, - pos: Vec3i, + starship: ActiveStarship, + pos: Vec3i, ) : WeaponSubsystem(starship, pos), ManualWeaponSubsystem, HeavyWeaponSubsystem, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CthulhuBeamWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CthulhuBeamWeaponSubsystem.kt index d6e075bef2..0546e59495 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CthulhuBeamWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CthulhuBeamWeaponSubsystem.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.proje import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AutoWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamethrowerWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamethrowerWeaponSubsystem.kt index 9f122c51df..0444e45976 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamethrowerWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamethrowerWeaponSubsystem.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.projectile.FlamethrowerProjectile import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/MiniPhaserWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/MiniPhaserWeaponSubsystem.kt index 5d3c1a80a6..1a3a6c65df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/MiniPhaserWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/MiniPhaserWeaponSubsystem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.projectile.MiniPhaserProjectile import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt index ac72a8d123..24600e1cb2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt @@ -9,18 +9,18 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsy import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.projectile.PumpkinCannonProjectile import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.util.Vector class PumpkinCannonWeaponSubsystem( - starship: ActiveStarship, - pos: Vec3i, - override var face: BlockFace + starship: ActiveStarship, + pos: Vec3i, + override var face: BlockFace ) : WeaponSubsystem(starship, pos), ManualWeaponSubsystem, DirectionalSubsystem, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/SonicMissileWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/SonicMissileWeaponSubsystem.kt index 5652166c7d..828710e879 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/SonicMissileWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/SonicMissileWeaponSubsystem.kt @@ -8,8 +8,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.proje import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.kyori.adventure.text.Component +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/CapitalBeamCannonProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/CapitalBeamCannonProjectile.kt index 2405277a11..0de57aedff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/CapitalBeamCannonProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/CapitalBeamCannonProjectile.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.ParticleProjectile -import net.horizonsend.ion.server.miscellaneous.utils.helixAroundVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.helixAroundVector import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.Particle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/PumpkinCannonProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/PumpkinCannonProjectile.kt index 1acc35568d..ad1407db81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/PumpkinCannonProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/projectile/PumpkinCannonProjectile.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.BlockProjectile import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt index 561a6eaf0a..8d8ab7dbe2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.HeavyTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import java.util.concurrent.TimeUnit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt index 74a54fc5f2..5dc57c46d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LaserCannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LaserCannonWeaponSubsystem.kt index 87de53af3c..723b3cf1a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LaserCannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LaserCannonWeaponSubsystem.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.CannonLaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt index e7cddec1b8..d1803b12ef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.AutoTurretTargeting.AutoTurr import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AutoWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PlasmaCannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PlasmaCannonWeaponSubsystem.kt index 0ccad20588..940bf95d56 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PlasmaCannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PlasmaCannonWeaponSubsystem.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.PlasmaLaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PointDefenseSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PointDefenseSubsystem.kt index 05987cacde..d27b7a6a9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PointDefenseSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PointDefenseSubsystem.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsyst import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AutoWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.PointDefenseLaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PulseCannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PulseCannonWeaponSubsystem.kt index 4402e0479a..abe98e94cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PulseCannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/PulseCannonWeaponSubsystem.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.PulseLaserProjectile import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.DyeColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt index b50eef7639..f0dd6e6a72 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ArsenalRocketProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ArsenalRocketProjectile.kt index 1c246ae0da..9bd80653bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ArsenalRocketProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ArsenalRocketProjectile.kt @@ -8,9 +8,9 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockPos import net.horizonsend.ion.server.miscellaneous.utils.gayColors import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.toBlockPos import net.kyori.adventure.key.Key import net.kyori.adventure.sound.Sound import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/BlockProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/BlockProjectile.kt index 8bf2075e57..b7ad551ce8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/BlockProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/BlockProjectile.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.Projectiles import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/IonTurretProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/IonTurretProjectile.kt index 300595576e..20645910ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/IonTurretProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/IonTurretProjectile.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.helixAroundVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.helixAroundVector import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.Location @@ -30,7 +30,6 @@ class IonTurretProjectile( override val soundName: String, override val balancing: StarshipWeapons.ProjectileBalancing?, shooter: Damager - ): LaserProjectile(ship, name, loc, dir, shooter) { override val volume: Int = (range / 16).toInt() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/RocketProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/RocketProjectile.kt index 4d85710849..b23a4b7848 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/RocketProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/RocketProjectile.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/VisualProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/VisualProjectile.kt index eebf142552..f97c612e40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/VisualProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/VisualProjectile.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile import net.horizonsend.ion.server.configuration.AntiAirCannonBalancing import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.starship.damager.noOpDamager -import net.horizonsend.ion.server.miscellaneous.utils.alongVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.alongVector import org.bukkit.Color import org.bukkit.Location import org.bukkit.Particle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIHeavyLaserWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIHeavyLaserWeaponSubsystem.kt index 4692ed7eff..7818a74a04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIHeavyLaserWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIHeavyLaserWeaponSubsystem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.TargetTrack import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.HeavyLaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt index 45909d6327..f292714c30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces. import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.ArsenalRocketProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/HeavyLaserWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/HeavyLaserWeaponSubsystem.kt index 84865d8e9e..e6a87ffef3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/HeavyLaserWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/HeavyLaserWeaponSubsystem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.TargetTrack import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.HeavyLaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/PhaserWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/PhaserWeaponSubsystem.kt index e381d1a8d0..7f54cd21d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/PhaserWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/PhaserWeaponSubsystem.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.PhaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt index d91eecfe09..bc88c0be88 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt @@ -11,7 +11,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces. import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.RocketProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TorpedoWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TorpedoWeaponSubsystem.kt index 898347c1dc..6733de0112 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TorpedoWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TorpedoWeaponSubsystem.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TargetTrackingCannonWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.TorpedoProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt index 37564fd46b..2c135542ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AutoWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt new file mode 100644 index 0000000000..7d6b4cef55 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt @@ -0,0 +1,38 @@ +package net.horizonsend.ion.server.features.transport + +import net.horizonsend.ion.server.features.multiblock.entity.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.world.IonChunk +import java.util.concurrent.ConcurrentHashMap + +class ChunkPowerNetwork( + val chunk: IonChunk, + val extractorData: ExtractorData +) { + init { + setup() + } + + private fun setup() { + + } + + fun tick() { + + } + + fun save() { + + } + + private fun getPowerMultiblockEntities(): ConcurrentHashMap { + val poweredMultiblockEntities = ConcurrentHashMap() + + chunk.getAllMultiblockEntities().forEach { (key, entity) -> + if (entity !is PoweredMultiblockEntity) return@forEach + + poweredMultiblockEntities[key] = entity + } + + return poweredMultiblockEntities + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt new file mode 100644 index 0000000000..c75b6cc03a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt @@ -0,0 +1,31 @@ +package net.horizonsend.ion.server.features.transport + +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.toVec3i +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType +import java.util.concurrent.ConcurrentLinkedQueue + +class ExtractorData( + val extractorLocations: ConcurrentLinkedQueue +) { + companion object : PersistentDataType, ExtractorData> { + override fun getPrimitiveType(): Class> = Array::class.java + override fun getComplexType(): Class = ExtractorData::class.java + + override fun fromPrimitive(primitive: Array, context: PersistentDataAdapterContext): ExtractorData { + val list = ConcurrentLinkedQueue() + + for (key in primitive) { + list.add(toVec3i(key)) + } + + return ExtractorData(list) + } + + override fun toPrimitive(complex: ExtractorData, context: PersistentDataAdapterContext): Array { + return complex.extractorLocations.map { toBlockKey(it) }.toTypedArray() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt index 28b2f54e5f..c273a58819 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt @@ -8,8 +8,8 @@ import net.horizonsend.ion.server.features.transport.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.pipe.filter.Filters import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.coordinates import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt index 384509918d..68f73ad3a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt index c66967742c..96a46aae46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.pipe import net.horizonsend.ion.server.features.transport.pipe.filter.FilterItemData -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt index cb8a5f7397..28d0266f42 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt @@ -14,11 +14,11 @@ import net.horizonsend.ion.server.features.transport.transportConfig import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.MATERIALS import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.chunkKey -import net.horizonsend.ion.server.miscellaneous.utils.chunkKeyX -import net.horizonsend.ion.server.miscellaneous.utils.chunkKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKeyZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt index b2e2fed9aa..7689b2d0ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.pipe.filter -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import java.util.UUID data class FilterDataKey(val world: UUID, val pos: Vec3i) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt index 30d5178096..e486db2954 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt @@ -6,7 +6,7 @@ import com.google.common.cache.LoadingCache import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Bukkit import org.bukkit.World import org.bukkit.block.Block diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/tutorial/tutorials/FlightTutorial.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/tutorial/tutorials/FlightTutorial.kt index c6f7f2a2cb..4114bf2f59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/tutorial/tutorials/FlightTutorial.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/tutorial/tutorials/FlightTutorial.kt @@ -24,7 +24,7 @@ import net.horizonsend.ion.server.features.tutorial.Tutorials import net.horizonsend.ion.server.features.tutorial.message.ActionMessage import net.horizonsend.ion.server.features.tutorial.message.PopupMessage import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.execConsoleCmd import net.horizonsend.ion.server.miscellaneous.utils.listen import net.horizonsend.ion.server.miscellaneous.utils.paste diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 847d9d1ac7..5420c8dd25 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -1,38 +1,51 @@ package net.horizonsend.ion.server.features.world import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.type.TickingMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.transport.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.ExtractorData import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.EXTRACTOR_DATA +import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey import org.bukkit.Chunk import org.bukkit.World +import org.bukkit.block.Sign import org.bukkit.event.EventHandler import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER_ARRAY import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentLinkedQueue class IonChunk(private val inner: Chunk) { val locationKey = inner.chunkKey - //TODO - // - Wires - // - Ore upgrade - // - + val originX = inner.x.shl(4) + val originZ = inner.z.shl(4) + // TODO + // - Wires + // - Ore upgrader + // - + + val powerNetwork: ChunkPowerNetwork = ChunkPowerNetwork(this, getExtractorData(inner)) /** * Logic upon loading the chunk **/ fun onLoad() { + // Load all multiblocks from persistent data loadMultiblocks() + collectTickedMultiblocks() } /** @@ -53,6 +66,7 @@ class IonChunk(private val inner: Chunk) { * Logic upon world tick **/ fun tick() { + powerNetwork.tick() tickMultiblocks() } @@ -74,6 +88,7 @@ class IonChunk(private val inner: Chunk) { val ionWorld = chunk.world.ion val ionChunk = IonChunk(chunk) + ionWorld.addChunk(ionChunk) ionChunk.onLoad() @@ -98,28 +113,58 @@ class IonChunk(private val inner: Chunk) { operator fun get(world: World, x: Int, z: Int): IonChunk? { return world.ion.getChunk(x, z) } + + private fun getExtractorData(chunk: Chunk): ExtractorData { + val extractors = chunk.persistentDataContainer.get(EXTRACTOR_DATA, ExtractorData) + + return extractors ?: ExtractorData(ConcurrentLinkedQueue()) + } + + fun Chunk.ion(): IonChunk = this.world.ion.getChunk(chunkKey)!! } private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() - private val tickingMultiblocks: ConcurrentHashMap = ConcurrentHashMap() + private val tickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + + fun getAllMultiblockEntities() = multiblockEntities /** * Add a new multiblock to the chunk data **/ - fun addMultiblock(multiblock: Multiblock, x: Int, y: Int, z: Int) { + fun addMultiblock(multiblock: Multiblock, sign: Sign) { + val (x, y, z) = Multiblock.getOrigin(sign) + val signOffset = sign.getFacing() + val key = toBlockKey(x, y, z) - if (multiblock is TickingMultiblock) { - tickingMultiblocks[key] = multiblock + if (multiblockEntities.containsKey(key)) { + log.warn("Attempted to place a multiblock where one already existed!") + return + } + + if (multiblock is TickingMultiblockEntity) { + tickingMultiblockEntities[key] = multiblock } if (multiblock !is EntityMultiblock<*>) return - val data = PersistentMultiblockData(x, y, z, multiblock) + val data = PersistentMultiblockData(x, y, z, multiblock, signOffset) - val entity = multiblock.createEntity(data, inner.world, x, y, z) + val entity = multiblock.createEntity(data, inner.world, x, y, z, signOffset.oppositeFace) multiblockEntities[key] = entity + + saveMultiblocks() + } + + /** + * Upon the removal of a multiblock sign + **/ + fun removeMultiblock(x: Int, y: Int, z: Int) { + val key = toBlockKey(x, y, z) + + multiblockEntities.remove(key) + tickingMultiblockEntities.remove(key) } fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { @@ -129,11 +174,19 @@ class IonChunk(private val inner: Chunk) { } private fun tickMultiblocks() { - tickingMultiblocks.values.forEach { - if (it.tickAsync) { - Multiblocks.context.launch { it.tick() } - } else { - it.tick() + tickingMultiblockEntities.forEach { (key, multiblock) -> + try { +// multiblock as MultiblockEntity +// if (!multiblock.isIntact()) { +// tickingMultiblockEntities.remove(key) +// } + + if (multiblock.tickAsync) { + Multiblocks.context.launch { multiblock.tick() } + } else runBlocking { multiblock.tick() } + } catch (e: Throwable) { + log.warn("Exception ticking multiblock ${e.message}") + e.printStackTrace() } } } @@ -149,12 +202,20 @@ class IonChunk(private val inner: Chunk) { val multiblock = stored.type as EntityMultiblock<*> - val entity = multiblock.createEntity(stored, inner.world, stored.x, stored.y, stored.z) + val entity = multiblock.createEntity(stored, inner.world, stored.x, stored.y, stored.z, stored.signOffset) loadMultiblockEntity(entity) } } + private fun collectTickedMultiblocks() { + for ((location, multiblock) in multiblockEntities) { + if (multiblock !is TickingMultiblockEntity) continue + + tickingMultiblockEntities[location] = multiblock + } + } + /** * Loads a multiblock entity from storage **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 9c5ea6db20..b7686a4c86 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -20,6 +20,7 @@ import org.bukkit.event.EventHandler import org.bukkit.event.world.WorldInitEvent import org.bukkit.event.world.WorldSaveEvent import org.bukkit.event.world.WorldUnloadEvent +import java.util.concurrent.ConcurrentHashMap import org.bukkit.persistence.PersistentDataType.LONG_ARRAY import kotlin.DeprecationLevel.ERROR @@ -32,7 +33,7 @@ class IonWorld private constructor( * * Value: The IonChunk at that location **/ - private val chunks: MutableMap = mutableMapOf() + private val chunks: ConcurrentHashMap = ConcurrentHashMap() /** * Gets the IonChunk at the specified coordinates if it is loaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/Environment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/Environment.kt index 8f3e16da08..3fe0711190 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/Environment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/environment/Environment.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.custom.items.component.CustomComponen import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModRegistry import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown -import net.horizonsend.ion.server.miscellaneous.utils.isInside +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isInside import net.horizonsend.ion.server.miscellaneous.utils.listen import org.bukkit.GameMode import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt index 94ed020aca..cc842263aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt @@ -11,9 +11,9 @@ import net.horizonsend.ion.server.features.world.generation.WorldGenerationManag import net.horizonsend.ion.server.features.world.generation.generators.interfaces.WorldGenerator import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.WeightedRandomList -import net.horizonsend.ion.server.miscellaneous.utils.component1 -import net.horizonsend.ion.server.miscellaneous.utils.component2 -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component1 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component2 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.readSchematic import net.minecraft.world.level.ChunkPos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/GameplayTweaksListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/GameplayTweaksListeners.kt index 9484109fd5..5fd699df60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/GameplayTweaksListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/GameplayTweaksListeners.kt @@ -5,10 +5,10 @@ import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships import net.horizonsend.ion.server.features.starship.StarshipState import net.horizonsend.ion.server.features.starship.event.StarshipPilotEvent import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.utils.blockKey -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.data.BlockData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt index 2c2cec27bd..8b69ca0745 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt @@ -1,17 +1,12 @@ package net.horizonsend.ion.server.listener.misc import net.horizonsend.ion.common.extensions.successActionMessage -import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.isBed import org.bukkit.block.Sign import org.bukkit.event.EventHandler import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.EquipmentSlot object InteractListener : SLEventListener() { // Put power into the sign if right clicking with a battery @@ -41,22 +36,6 @@ object InteractListener : SLEventListener() { } */ - @EventHandler - fun handleMultiblockInteract(event: PlayerInteractEvent) { - if (event.hand != EquipmentSlot.HAND) return - if (event.action != Action.RIGHT_CLICK_BLOCK) return - val player = event.player - - val sign = event.clickedBlock?.getState(false) as? Sign ?: return - (Multiblocks[sign, true, false] as? InteractableMultiblock)?.let { multiblock -> - (multiblock as Multiblock).requiredPermission?.let { permission -> - if (!player.hasPermission(permission)) return player.userError("You don't have permission to use that multiblock!") - } - - multiblock.onSignInteract(sign, player, event) - } - } - // Disable beds @EventHandler fun onPlayerInteractEventH(event: PlayerInteractEvent) { @@ -66,9 +45,7 @@ object InteractListener : SLEventListener() { if (item.type.isBed) { event.isCancelled = true - player.successActionMessage( - "Beds are disabled on this server! Use a cryopod instead" - ) + player.successActionMessage("Beds are disabled on this server! Use a cryopod instead") } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt index 99b9785db4..6aad8b4865 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt @@ -21,14 +21,13 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.action import net.horizonsend.ion.server.miscellaneous.utils.colorize -import net.horizonsend.ion.server.miscellaneous.utils.component1 -import net.horizonsend.ion.server.miscellaneous.utils.component2 -import net.horizonsend.ion.server.miscellaneous.utils.component3 -import net.horizonsend.ion.server.miscellaneous.utils.component4 -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component1 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component2 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component3 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component4 import net.horizonsend.ion.server.miscellaneous.utils.isPilot import net.horizonsend.ion.server.miscellaneous.utils.msg import org.bukkit.Location diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt index 9238486060..d137bc1537 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.command.admin.CustomItemCommand import net.horizonsend.ion.server.command.admin.DisplayDebug import net.horizonsend.ion.server.command.admin.ForbiddenBlocksCommand import net.horizonsend.ion.server.command.admin.GracePeriod +import net.horizonsend.ion.server.command.admin.IonChunkCommand import net.horizonsend.ion.server.command.admin.IonCommand import net.horizonsend.ion.server.command.admin.ItemDebugCommand import net.horizonsend.ion.server.command.admin.RemoveGhostShipCommand @@ -150,6 +151,7 @@ val commands: List = listOf( SpaceGenCommand, ConfigurationCommands, WorldCommand, + IonChunkCommand, CustomItemCommand, IonCommand, SearchCommand, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index d319407530..4b1a64be67 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -7,8 +7,9 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemListeners import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporterManager import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners import net.horizonsend.ion.server.features.machine.CryoPods -import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager @@ -54,6 +55,7 @@ val listeners: List = listOf( EntityListener, FurnaceListener, InteractListener, + InteractableMultiblock, InventoryListener, BowHitListener, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index e6703c6ce4..0eb2d426ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -45,8 +45,9 @@ object NamespacedKeys { val COMBAT_NPC = key("combatnpc") val MULTIBLOCK = key("multiblock") - val ADDITIONAL_MULTIBLOCK_DATA = key("additionalMultiblockData") - val MULTIBLOCK_ENTITY_DATA = key("multiblockEntityData") + val ADDITIONAL_MULTIBLOCK_DATA = key("additional_multiblock_data") + val MULTIBLOCK_ENTITY_DATA = key("multiblock_entity_data") + val MULTIBLOCK_SIGN_OFFSET = key("multiblock_sign_offset") val CUSTOM_ENTITY = key("custom_entity") @@ -79,7 +80,8 @@ object NamespacedKeys { val FORBIDDEN_BLOCKS = key("forbidden_blocks") val CARGO_CRATE = key("cargo_crate") - val STORED_MULTIBLOCK_ENTITIES = key("storedMultiblocKEntities") + val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") + val EXTRACTOR_DATA = key("extractor_data") fun key(key: String) = NamespacedKey(IonServer, key) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt index 10ed9cd022..9b40804849 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/StoredPosition.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.miscellaneous.registrations.persistence -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt index 91d7e671cb..49b3537bee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt @@ -6,6 +6,8 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.command.admin.IonCommand import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.machine.AreaShields +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.audience.Audience import net.kyori.adventure.audience.ForwardingAudience import net.milkbowl.vault.economy.Economy import net.minecraft.core.BlockPos diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NMS.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NMS.kt index 98946dba50..1dadd90546 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NMS.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NMS.kt @@ -12,6 +12,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData import org.bukkit.craftbukkit.CraftChunk import org.bukkit.craftbukkit.block.data.CraftBlockData +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i //region Access Extensions inline val BlockData.nms: BlockState get() = (this as CraftBlockData).state diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt index 3799997615..490f7c0594 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt @@ -1,9 +1,11 @@ package net.horizonsend.ion.server.miscellaneous.utils +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.minecraft.core.BlockPos /** * Packs a x, y, z coordinate into a long **/ fun toBlockKey(x: Int, y: Int, z: Int): Long = BlockPos.asLong(x, y, z) +fun toBlockKey(vec3i: Vec3i): Long = BlockPos.asLong(vec3i.x, vec3i.y, vec3i.z) fun toVec3i(key: Long): Vec3i = Vec3i(BlockPos.getX(key), BlockPos.getY(key), BlockPos.getZ(key)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/ServerDBBridge.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/ServerDBBridge.kt index 581adb3a85..4a0617518f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/ServerDBBridge.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/ServerDBBridge.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.miscellaneous.utils import com.sk89q.worldedit.extent.clipboard.Clipboard -import com.sk89q.worldedit.math.BlockVector3 import net.horizonsend.ion.common.database.SLTextStyleDB import net.horizonsend.ion.common.database.StarshipTypeDB import net.horizonsend.ion.common.database.schema.Cryopod @@ -12,7 +11,6 @@ import net.horizonsend.ion.common.database.schema.starships.PlayerStarshipData import net.horizonsend.ion.common.database.schema.starships.StarshipData import net.horizonsend.ion.common.database.slPlayerId import net.horizonsend.ion.common.extensions.CommonPlayer -import net.horizonsend.ion.common.utils.DBVec3i import net.horizonsend.ion.common.utils.luckPerms import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.starship.StarshipSchematic @@ -23,7 +21,6 @@ import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.World import org.bukkit.entity.Player -import org.bukkit.util.Vector import java.util.Base64 import java.util.UUID @@ -75,43 +72,3 @@ class CommonPlayerWrapper(private val inner: Player) : CommonPlayer { fun Player.common(): CommonPlayer = CommonPlayerWrapper(this) } } - -class Vec3i: DBVec3i { - constructor(a: DBVec3i) : super(a.x, a.y, a.z) - constructor(x: Int, y: Int, z: Int) : super(x, y, z) - @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") - constructor(blockKey: Long) : super(blockKeyX(blockKey), blockKeyY(blockKey), blockKeyZ(blockKey)) - - constructor(vector: Vector) : super(vector.blockX, vector.blockY, vector.blockZ) - - constructor(location: Location) : super(location.blockX, location.blockY, location.blockZ) - - constructor(vector: BlockVector3) : super(vector.x(), vector.y(), vector.z()) - - fun toLocation(world: World): Location = Location(world, x.toDouble(), y.toDouble(), z.toDouble()) - - @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") - fun toBlockKey(): Long = blockKey(x, y, z) - - fun toVector(): Vector = Vector(x, y, z) - fun toCenterVector(): Vector = Vector(x.toDouble() + 0.5, y.toDouble() + 0.5, z.toDouble() + 0.5) - - fun distance(x: Int, y: Int, z: Int): Double = distance(this.x, this.y, this.z, x, y, z) - fun distance(other: Vec3i): Double = distance(this.x, this.y, this.z, other.x, other.y, other.z) - - /** - * @param other Vector that should be added from this one - * @return A new vector with the values added - **/ - operator fun plus(other: Vec3i) = Vec3i(x + other.x, y + other.y, z + other.z) - - /** - * @param other Vector that should be subtracted from this one - * @return A new vector with the values subtracted - **/ - operator fun minus(other: Vec3i) = Vec3i(x - other.x, y - other.y, z - other.z) - - fun below(blocks: Int = 1) = Vec3i(x, y - blocks, z) - operator fun times(m: Double): Vec3i = Vec3i((x * m).toInt(), (y * m).toInt(), (z * m).toInt()) - operator fun times(m: Int): Vec3i = Vec3i((x * m), (y * m), (z * m)) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/WorldEdit.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/WorldEdit.kt index f22c5a3ccd..33dd086065 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/WorldEdit.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/WorldEdit.kt @@ -16,6 +16,8 @@ import com.sk89q.worldedit.world.block.BlockState as WorldEditBlockState import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.minecraft.nbt.ByteArrayTag import net.minecraft.nbt.ByteTag import net.minecraft.nbt.DoubleTag diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Coordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Coordinates.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt index b519bcef7f..53bf22dde2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Coordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.miscellaneous.utils +package net.horizonsend.ion.server.miscellaneous.utils.coordinates import net.horizonsend.ion.common.utils.miscellaneous.d import net.horizonsend.ion.common.utils.miscellaneous.squared diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt new file mode 100644 index 0000000000..a3eaaf3e0d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt @@ -0,0 +1,47 @@ +package net.horizonsend.ion.server.miscellaneous.utils.coordinates + +import com.sk89q.worldedit.math.BlockVector3 +import net.horizonsend.ion.common.utils.DBVec3i +import org.bukkit.Location +import org.bukkit.World +import org.bukkit.util.Vector + +class Vec3i: DBVec3i { + constructor(a: DBVec3i) : super(a.x, a.y, a.z) + constructor(x: Int, y: Int, z: Int) : super(x, y, z) + @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") + constructor(blockKey: Long) : super(blockKeyX(blockKey), blockKeyY(blockKey), blockKeyZ(blockKey)) + + constructor(vector: Vector) : super(vector.blockX, vector.blockY, vector.blockZ) + + constructor(location: Location) : super(location.blockX, location.blockY, location.blockZ) + + constructor(vector: BlockVector3) : super(vector.blockX, vector.blockY, vector.blockZ) + + fun toLocation(world: World): Location = Location(world, x.toDouble(), y.toDouble(), z.toDouble()) + + @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") + fun toBlockKey(): Long = blockKey(x, y, z) + + fun toVector(): Vector = Vector(x, y, z) + fun toCenterVector(): Vector = Vector(x.toDouble() + 0.5, y.toDouble() + 0.5, z.toDouble() + 0.5) + + fun distance(x: Int, y: Int, z: Int): Double = distance(this.x, this.y, this.z, x, y, z) + fun distance(other: Vec3i): Double = distance(this.x, this.y, this.z, other.x, other.y, other.z) + + /** + * @param other Vector that should be added from this one + * @return A new vector with the values added + **/ + operator fun plus(other: Vec3i) = Vec3i(x + other.x, y + other.y, z + other.z) + + /** + * @param other Vector that should be subtracted from this one + * @return A new vector with the values subtracted + **/ + operator fun minus(other: Vec3i) = Vec3i(x - other.x, y - other.y, z - other.z) + + fun below(blocks: Int = 1) = Vec3i(x, y - blocks, z) + operator fun times(m: Double): Vec3i = Vec3i((x * m).toInt(), (y * m).toInt(), (z * m).toInt()) + operator fun times(m: Int): Vec3i = Vec3i((x * m), (y * m), (z * m)) +} From a40b22dc2c4721a619c7b54da12be784adb65707 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 14 Mar 2024 02:27:38 -0500 Subject: [PATCH 010/500] move ionChunk multiblock management stuff to its own thing, fixes, cleanup --- .../server/command/admin/IonChunkCommand.kt | 16 +- .../multiblock/ChunkMultiblockManager.kt | 160 ++++++++++++++++++ .../server/features/multiblock/Multiblocks.kt | 23 ++- .../multiblock/entity/MultiblockEntity.kt | 3 + .../multiblock/type/misc/TestMultiblock.kt | 5 + .../type/starshipweapon/EntityMultiblock.kt | 2 +- .../features/transport/ChunkPowerNetwork.kt | 14 +- .../ion/server/features/world/IonChunk.kt | 152 +---------------- .../ion/server/features/world/IonWorld.kt | 3 - .../miscellaneous/utils/IntervalExecutor.kt | 18 ++ .../utils/coordinates/RelativeCoordinates.kt | 20 +++ 11 files changed, 255 insertions(+), 161 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/IntervalExecutor.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index a1625e51e8..4de28bed80 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -15,7 +15,7 @@ import org.bukkit.entity.Player object IonChunkCommand : SLCommand() { @Subcommand("dumpEntities") fun onDumpEntities(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { - val entities = sender.chunk.ion().getAllMultiblockEntities().toList() + val entities = sender.chunk.ion().multiblockManager.getAllMultiblockEntities().toList() sender.sendMessage(formatPaginatedMenu( entities.size, @@ -26,7 +26,7 @@ object IonChunkCommand : SLCommand() { val vec = toVec3i(key) - text("$vec : ${entity.type}") + text("$vec : $entity") }) if (visual == true) { @@ -37,4 +37,16 @@ object IonChunkCommand : SLCommand() { } } } + + @Subcommand("remove all") + fun onRemoveAll(sender: Player) { + val ionChunk = sender.chunk.ion() + val entities = ionChunk.multiblockManager.getAllMultiblockEntities() + + for ((key, _) in entities) { + val (x, y, z) = toVec3i(key) + + ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt new file mode 100644 index 0000000000..828255f7d5 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -0,0 +1,160 @@ +package net.horizonsend.ion.server.features.multiblock + +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey +import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataType.LIST +import org.slf4j.LoggerFactory +import java.util.concurrent.ConcurrentHashMap + +class ChunkMultiblockManager(val chunk: IonChunk) { + private val log = LoggerFactory.getLogger("ChunkMutliblockManager[$chunk]") + + /** All the loaded multiblock entities of this chunk */ + private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + + /** All the ticked multiblock entities of this chunk */ + private val tickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + + /** + * Logic upon the chunk being ticked + **/ + fun tick() { + tickAllMultiblocks() + } + + /** + * Logic upon the chunk being saved + **/ + fun save() { + saveMultiblocks() + } + + init { + loadMultiblocks() + } + + fun getAllMultiblockEntities() = multiblockEntities + + private fun tickAllMultiblocks() = tickingMultiblockEntities.forEachValue(tickingMultiblockEntities.size.toLong(), ::handleMultiblockTick) + + private fun handleMultiblockTick(multiblock: TickingMultiblockEntity): Boolean = try { + if (multiblock.tickAsync) { + Multiblocks.context.launch { multiblock.tick() } + } else runBlocking { multiblock.tick() } + + true + } catch (e: Throwable) { + log.warn("Exception ticking multiblock ${e.message}") + e.printStackTrace() + + false + } + + /** + * Add a new multiblock to the chunk data + **/ + fun addNewMultiblockEntity(multiblock: EntityMultiblock<*>, sign: Sign) { + // Allow smart cast + multiblock as Multiblock + + val (x, y, z) = Multiblock.getOrigin(sign) + val signOffset = sign.getFacing() + + if (isOccupied(x, y, z)) { + log.warn("Attempted to place a multiblock where one already existed!") + return + } + + // Create new empty data + val entity = multiblock.createEntity( + PersistentMultiblockData(x, y, z, multiblock, signOffset), + chunk.inner.world, + x, y, z, + signOffset + ) + + // Place the entity into the chunk + addMultiblockEntity(entity) + } + + /** + * Handles the addition of a multiblock entity + **/ + fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true) { + multiblockEntities[entity.locationKey] = entity + + if (entity is TickingMultiblockEntity) { + tickingMultiblockEntities[entity.locationKey] = entity + } + + if (save) saveMultiblocks() + } + + /** + * Save the multiblock data back into the chunk + **/ + private fun saveMultiblocks() = Multiblocks.context.launch { + val array = multiblockEntities.map { (_, entity) -> + PersistentMultiblockData.toPrimitive(entity.store(), chunk.inner.persistentDataContainer.adapterContext) + } + + chunk.inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, LIST.dataContainers(), array) + chunk.inner.minecraft.isUnsaved = true + } + + /** + * Load the multiblocks from the persistent data container upon chunk load. + **/ + private fun loadMultiblocks() { + val serialized = chunk.inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, LIST.dataContainers()) ?: return + + for (serializedMultiblockData in serialized) { + val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, chunk.inner.persistentDataContainer.adapterContext) + + val multiblock = stored.type as EntityMultiblock<*> + + val entity = multiblock.createEntity(stored, chunk.inner.world, stored.x, stored.y, stored.z, stored.signOffset) + + // No need to save a load + addMultiblockEntity(entity, save = false) + } + } + + /** + * Upon the removal of a multiblock sign + **/ + fun removeMultiblockEntity(x: Int, y: Int, z: Int) { + val key = toBlockKey(x, y, z) + + multiblockEntities.remove(key) + tickingMultiblockEntities.remove(key) + } + + /** + * Get multiblock entity at these coordinates + **/ + operator fun get(x: Int, y: Int, z: Int): MultiblockEntity? { + val key = toBlockKey(x, y, z) + + return multiblockEntities[key] + } + + /** + * Get multiblock entity at this block key + **/ + operator fun get(key: Long): MultiblockEntity? { + return multiblockEntities[key] + } + + fun isOccupied(x: Int, y: Int, z: Int): Boolean = multiblockEntities.containsKey(toBlockKey(x, y, z)) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index cb3d81f1e4..f2ab7c1243 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -107,6 +107,7 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinter import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock @@ -508,13 +509,6 @@ object Multiblocks : IonServerComponent() { multiblock.setupSign(detector, sign) - val (x, y, z) = Multiblock.getOrigin(sign) - - val chunkX = x.shr(4) - val chunkZ = z.shr(4) - - val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - sign.persistentDataContainer.set( NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, @@ -527,9 +521,20 @@ object Multiblocks : IonServerComponent() { sign.update() } - chunk.addMultiblock(multiblock, sign) + if (multiblock is EntityMultiblock<*>) { + // Multiblock entities are stored inside the block that the sign is placed on + val (x, _, z) = Multiblock.getOrigin(sign) + + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync + + chunk.multiblockManager.addNewMultiblockEntity(multiblock, sign) + } } + /** Upon a multiblock being removed */ fun removeMultiblock(multiblock: Multiblock, sign: Sign, player: Player) = Tasks.sync { val (x, y, z) = Multiblock.getOrigin(sign) @@ -538,6 +543,6 @@ object Multiblocks : IonServerComponent() { val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - chunk.removeMultiblock(x, y, z) + chunk.multiblockManager.removeMultiblockEntity(x, y, z) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 52a0c40ed8..e4db158791 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey import org.bukkit.Location import org.bukkit.World import org.bukkit.block.BlockFace @@ -35,6 +36,8 @@ abstract class MultiblockEntity( **/ val vec3i get() = Vec3i(x, y, z) + val locationKey = toBlockKey(x, y, z) + /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 0f07044088..bc649777bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.type.InteractableMultibloc import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextDecoration import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer @@ -79,6 +80,10 @@ object TestMultiblock : Multiblock(), EntityMultiblock { val chunkZ = z.shr(4) @Suppress("UNCHECKED_CAST") - return world.ion.getChunk(chunkX, chunkZ)?.getMultiblockEntity(x, y, z) as T? + return world.ion.getChunk(chunkX, chunkZ)?.multiblockManager?.get(x, y, z) as T? } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt index 7d6b4cef55..81120e2964 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt @@ -2,12 +2,16 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.features.multiblock.entity.PoweredMultiblockEntity import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.Chunk import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentLinkedQueue class ChunkPowerNetwork( val chunk: IonChunk, - val extractorData: ExtractorData ) { + val extractorData = getExtractorData(chunk.inner) + init { setup() } @@ -27,7 +31,7 @@ class ChunkPowerNetwork( private fun getPowerMultiblockEntities(): ConcurrentHashMap { val poweredMultiblockEntities = ConcurrentHashMap() - chunk.getAllMultiblockEntities().forEach { (key, entity) -> + chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> if (entity !is PoweredMultiblockEntity) return@forEach poweredMultiblockEntities[key] = entity @@ -35,4 +39,10 @@ class ChunkPowerNetwork( return poweredMultiblockEntities } + + fun getExtractorData(chunk: Chunk): ExtractorData { + val extractors = chunk.persistentDataContainer.get(NamespacedKeys.EXTRACTOR_DATA, ExtractorData) + + return extractors ?: ExtractorData(ConcurrentLinkedQueue()) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 5420c8dd25..605d60e1f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -1,32 +1,16 @@ package net.horizonsend.ion.server.features.world -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.ExtractorData import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.EXTRACTOR_DATA -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey import org.bukkit.Chunk import org.bukkit.World -import org.bukkit.block.Sign import org.bukkit.event.EventHandler import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent -import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER_ARRAY -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ConcurrentLinkedQueue -class IonChunk(private val inner: Chunk) { +class IonChunk(val inner: Chunk) { val locationKey = inner.chunkKey val originX = inner.x.shl(4) @@ -35,17 +19,16 @@ class IonChunk(private val inner: Chunk) { // TODO // - Wires // - Ore upgrader - // - + // - Explosion Reversal - val powerNetwork: ChunkPowerNetwork = ChunkPowerNetwork(this, getExtractorData(inner)) + val multiblockManager = ChunkMultiblockManager(this) + val powerNetwork: ChunkPowerNetwork = ChunkPowerNetwork(this) /** * Logic upon loading the chunk **/ fun onLoad() { - // Load all multiblocks from persistent data - loadMultiblocks() - collectTickedMultiblocks() + } /** @@ -59,7 +42,7 @@ class IonChunk(private val inner: Chunk) { * Logic upon world save **/ fun save() { - saveMultiblocks() + multiblockManager.save() } /** @@ -67,7 +50,7 @@ class IonChunk(private val inner: Chunk) { **/ fun tick() { powerNetwork.tick() - tickMultiblocks() + multiblockManager.tick() } companion object : SLEventListener() { @@ -114,125 +97,6 @@ class IonChunk(private val inner: Chunk) { return world.ion.getChunk(x, z) } - private fun getExtractorData(chunk: Chunk): ExtractorData { - val extractors = chunk.persistentDataContainer.get(EXTRACTOR_DATA, ExtractorData) - - return extractors ?: ExtractorData(ConcurrentLinkedQueue()) - } - fun Chunk.ion(): IonChunk = this.world.ion.getChunk(chunkKey)!! } - - private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() - private val tickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() - - fun getAllMultiblockEntities() = multiblockEntities - - /** - * Add a new multiblock to the chunk data - **/ - fun addMultiblock(multiblock: Multiblock, sign: Sign) { - val (x, y, z) = Multiblock.getOrigin(sign) - val signOffset = sign.getFacing() - - val key = toBlockKey(x, y, z) - - if (multiblockEntities.containsKey(key)) { - log.warn("Attempted to place a multiblock where one already existed!") - return - } - - if (multiblock is TickingMultiblockEntity) { - tickingMultiblockEntities[key] = multiblock - } - - if (multiblock !is EntityMultiblock<*>) return - - val data = PersistentMultiblockData(x, y, z, multiblock, signOffset) - - val entity = multiblock.createEntity(data, inner.world, x, y, z, signOffset.oppositeFace) - - multiblockEntities[key] = entity - - saveMultiblocks() - } - - /** - * Upon the removal of a multiblock sign - **/ - fun removeMultiblock(x: Int, y: Int, z: Int) { - val key = toBlockKey(x, y, z) - - multiblockEntities.remove(key) - tickingMultiblockEntities.remove(key) - } - - fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { - val key = toBlockKey(x, y, z) - - return multiblockEntities[key] - } - - private fun tickMultiblocks() { - tickingMultiblockEntities.forEach { (key, multiblock) -> - try { -// multiblock as MultiblockEntity -// if (!multiblock.isIntact()) { -// tickingMultiblockEntities.remove(key) -// } - - if (multiblock.tickAsync) { - Multiblocks.context.launch { multiblock.tick() } - } else runBlocking { multiblock.tick() } - } catch (e: Throwable) { - log.warn("Exception ticking multiblock ${e.message}") - e.printStackTrace() - } - } - } - - /** - * Load the multiblocks from the persistent data container upon chunk load. - **/ - private fun loadMultiblocks() { - val serialized = inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) ?: return - - for (serializedMultiblockData in serialized) { - val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, inner.persistentDataContainer.adapterContext) - - val multiblock = stored.type as EntityMultiblock<*> - - val entity = multiblock.createEntity(stored, inner.world, stored.x, stored.y, stored.z, stored.signOffset) - - loadMultiblockEntity(entity) - } - } - - private fun collectTickedMultiblocks() { - for ((location, multiblock) in multiblockEntities) { - if (multiblock !is TickingMultiblockEntity) continue - - tickingMultiblockEntities[location] = multiblock - } - } - - /** - * Loads a multiblock entity from storage - **/ - private fun loadMultiblockEntity(entity: MultiblockEntity) { - val key = toBlockKey(entity.x, entity.y, entity.z) - - multiblockEntities[key] = entity - } - - /** - * Save the multiblock data back into the chunk - **/ - private fun saveMultiblocks() { - val array = multiblockEntities.map { (_, entity) -> - PersistentMultiblockData.toPrimitive(entity.store(), inner.persistentDataContainer.adapterContext) - }.toTypedArray() - - inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY, array) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index b7686a4c86..a128b92ac4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -109,9 +109,6 @@ class IonWorld private constructor( //TODO // - Terrain Generator - // - IonChunks - // - Wires - // - Explosion Reversal // - Area Shields // - // - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/IntervalExecutor.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/IntervalExecutor.kt new file mode 100644 index 0000000000..26f4806f29 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/IntervalExecutor.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.miscellaneous.utils + +/** + * Only runs the attempted task once this has been called the set number of times + **/ +class IntervalExecutor(private val interval: Int, private val execute: () -> Unit) { + var count: Int = 0; + + operator fun invoke() { + if (count >= interval) { + execute.invoke() + count = 0 + return + } + + count++ + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt new file mode 100644 index 0000000000..423a1bd02d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.miscellaneous.utils.coordinates + +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import org.bukkit.block.BlockFace + +fun toAbsolute(face: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { + val right = face.rightFace + + return Vec3i( + x = (right.modX * leftRight) + (face.modX * backFourth), + y = upDown, + z = (right.modZ * leftRight) + (face.modZ * backFourth) + ) +} + +fun getRelative(origin: Vec3i, face: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { + val relative = toAbsolute(face, backFourth, leftRight, upDown) + + return origin + relative +} From 55a861746cd0bc5451a342a0184bd2fb27440229 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 14 Mar 2024 03:30:16 -0500 Subject: [PATCH 011/500] use common utils, refactoring --- .../net/horizonsend/ion/server/IonServer.kt | 2 +- .../server/command/admin/IonChunkCommand.kt | 2 +- .../command/misc/IonBroadcastCommand.kt | 2 +- .../server/command/nations/NationCommand.kt | 1 + .../command/nations/NationRelationCommand.kt | 2 +- .../utils => features/chat}/Discord.kt | 2 +- .../multiblock/ChunkMultiblockManager.kt | 2 +- .../features/multiblock/MultiblockShape.kt | 8 +-- .../server/features/multiblock/Multiblocks.kt | 2 +- .../multiblock/entity/MultiblockEntity.kt | 24 ++++++-- .../entity/PoweredMultiblockEntity.kt | 4 +- .../multiblock/type/misc/TestMultiblock.kt | 2 +- .../features/nations/sieges/StationSieges.kt | 2 +- .../features/transport/ExtractorData.kt | 4 +- .../server/listener/misc/JoinLeaveListener.kt | 2 +- .../miscellaneous/registrations/Components.kt | 2 +- .../ion/server/miscellaneous/utils/Chat.kt | 55 ------------------- .../ion/server/miscellaneous/utils/Notify.kt | 3 +- .../ion/server/miscellaneous/utils/Sounds.kt | 6 -- .../ion/server/miscellaneous/utils/Vault.kt | 4 -- .../utils/{ => coordinates}/NewBlockKey.kt | 3 +- .../utils/{ => coordinates}/Position.kt | 2 +- .../utils/coordinates/RelativeCoordinates.kt | 8 +-- 23 files changed, 45 insertions(+), 99 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/{miscellaneous/utils => features/chat}/Discord.kt (98%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Sounds.kt rename server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/{ => coordinates}/NewBlockKey.kt (72%) rename server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/{ => coordinates}/Position.kt (55%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt index f7ec9c9495..b6828ae1a7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.command.GlobalCompletions import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.ConfigurationFiles.configurationFolder +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.client.networking.packets.ShipData import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.generation.generators.bukkit.EmptyChunkGenerator @@ -19,7 +20,6 @@ import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.commands import net.horizonsend.ion.server.miscellaneous.registrations.components import net.horizonsend.ion.server.miscellaneous.registrations.listeners -import net.horizonsend.ion.server.miscellaneous.utils.Discord import net.horizonsend.ion.server.miscellaneous.utils.Tasks import org.bukkit.Bukkit import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 4de28bed80..47e52d72ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.world.IonChunk.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/IonBroadcastCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/IonBroadcastCommand.kt index a4386cfaf5..51fb49301c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/IonBroadcastCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/IonBroadcastCommand.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.utils.discord.Embed import net.horizonsend.ion.common.utils.text.subStringBetween import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.miscellaneous.utils.Discord +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.kyori.adventure.text.minimessage.MiniMessage.miniMessage diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt index 5064a6532f..a2772346fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt @@ -30,6 +30,7 @@ import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.cache.PlayerCache +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.nations.NATIONS_BALANCE import net.horizonsend.ion.server.features.nations.region.Regions import net.horizonsend.ion.server.features.nations.region.types.RegionTerritory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationRelationCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationRelationCommand.kt index 5b471bd508..d69505b364 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationRelationCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationRelationCommand.kt @@ -18,7 +18,7 @@ import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.miscellaneous.utils.Discord +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.kyori.adventure.audience.Audience import net.kyori.adventure.text.Component.newline diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Discord.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/Discord.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Discord.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/chat/Discord.kt index 087de43cfa..ce0cb2e138 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Discord.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/chat/Discord.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.miscellaneous.utils +package net.horizonsend.ion.server.features.chat import dev.vankka.mcdiscordreserializer.discord.DiscordSerializer import dev.vankka.mcdiscordreserializer.discord.DiscordSerializerOptions diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 828255f7d5..19cc462293 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -8,9 +8,9 @@ import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEn import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataType.LIST import org.slf4j.LoggerFactory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt index 1c95262101..4b2f798265 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt @@ -20,6 +20,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.STAINED_TERRACOTTA_TYPES import net.horizonsend.ion.server.miscellaneous.utils.TERRACOTTA_TYPES import net.horizonsend.ion.server.miscellaneous.utils.blockFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toAbsolute import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockData import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe @@ -40,7 +41,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.isStairs import net.horizonsend.ion.server.miscellaneous.utils.isTrapdoor import net.horizonsend.ion.server.miscellaneous.utils.isWall import net.horizonsend.ion.server.miscellaneous.utils.isWool -import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.minecraft.world.level.block.AbstractFurnaceBlock import org.bukkit.Material import org.bukkit.Particle @@ -255,10 +255,8 @@ class MultiblockShape { } CARDINAL_BLOCK_FACES.forEach { inwardFace -> - val rightFace = inwardFace.rightFace - val x = rightFace.modX * right + inwardFace.modX * inward - val z = rightFace.modZ * right + inwardFace.modZ * inward - val intTrio = Vec3i(x, upward, z) + val intTrio = toAbsolute(inwardFace, inward, right, upward) + val requirementMap = getRequirementMap(inwardFace) requirementMap[intTrio] = requirement diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index f2ab7c1243..945a06114a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -147,9 +147,9 @@ import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.isSign -import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey import org.bukkit.World import org.bukkit.block.Sign import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index e4db158791..08ece4222d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -3,9 +3,11 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Location import org.bukkit.World +import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -19,12 +21,13 @@ import org.bukkit.block.Sign * @param type The type of multiblock this entity represents **/ abstract class MultiblockEntity( - val x: Int, - val y: Int, - val z: Int, - val world: World, val type: Multiblock, - val signOffset: BlockFace + + var x: Int, + var y: Int, + var z: Int, + var world: World, + var signOffset: BlockFace ) { /** * Returns the origin of this multiblock as a Location @@ -71,4 +74,13 @@ abstract class MultiblockEntity( return type.signMatchesStructureAsync(sign) } + + /** + * + **/ + fun getBlockRelative(backFourth: Int, leftRight: Int, upDown: Int): Block { + val (x, y, z) = getRelative(vec3i, signOffset.oppositeFace, backFourth, leftRight, upDown) + + return world.getBlockAt(x, y, z) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt index cc19528bb8..64171e8aaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt @@ -9,14 +9,14 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign abstract class PoweredMultiblockEntity( + type: Multiblock, x: Int, y: Int, z: Int, world: World, - type: Multiblock, signOffset: BlockFace, private var power: Int -) : MultiblockEntity(x, y, z, world, type, signOffset) { +) : MultiblockEntity(type, x, y, z, world, signOffset) { init { require(type is PowerStoringMultiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index bc649777bb..9a98940a59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -57,7 +57,7 @@ object TestMultiblock : Multiblock(), EntityMultiblock = listOf( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Chat.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Chat.kt index 14947fa088..0a0388712f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Chat.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Chat.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.miscellaneous.utils -import com.destroystokyo.paper.Title import net.md_5.bungee.api.ChatColor import net.md_5.bungee.api.chat.TextComponent import org.bukkit.Bukkit @@ -35,9 +34,6 @@ infix fun Player.actionAndMsg(text: String) { this.msg(text) } -@Deprecated("Use Ion MiniMessage Extension Functions") -infix fun Player.title(title: Title) = sendTitle(title) - @Deprecated("Use Ion MiniMessage Extension Functions") fun Player.title( title: TextComponent = "".text(), @@ -57,30 +53,9 @@ fun String.colorize(): String = ChatColor.translateAlternateColorCodes('&', this @Deprecated("Use Ion MiniMessage Extension Functions") fun String.stripColor(): String = ChatColor.stripColor(this) -@Deprecated("Use Ion MiniMessage Extension Functions") -fun String.fromLegacy(): TextComponent = TextComponent(*TextComponent.fromLegacyText(this.colorize())) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun Iterable.joinToText( - commaColor: SLTextStyle = SLTextStyle.GRAY, - transform: (T) -> TextComponent = { toString().fromLegacy() } -): TextComponent { - val component = TextComponent() - val valueCount = this.count() - for ((index, value) in this.withIndex()) { - component.addExtra(transform(value)) - if (index >= valueCount - 1) continue - component.addExtra(", ".style(commaColor)) - } - return component -} - @Deprecated("Use Ion MiniMessage Extension Functions") fun String.text(): TextComponent = TextComponent(this) -@Deprecated("Use Ion MiniMessage Extension Functions") -operator fun TextComponent.plus(that: TextComponent) = apply { addExtra(that) } - @Deprecated("Use Ion MiniMessage Extension Functions") fun String.style(style: SLTextStyle) = text().style(style) @@ -90,45 +65,15 @@ fun TextComponent.style(style: SLTextStyle): TextComponent = apply { color = sty @Deprecated("Use Ion MiniMessage Extension Functions") fun TextComponent.bold() = apply { isBold = true } -@Deprecated("Use Ion MiniMessage Extension Functions") -fun TextComponent.italic() = apply { isItalic = true } - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun darkGreen(s: String) = s.style(SLTextStyle.DARK_GREEN) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun darkAqua(s: String) = s.style(SLTextStyle.DARK_AQUA) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun darkPurple(s: String) = s.style(SLTextStyle.DARK_PURPLE) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun gold(s: String) = s.style(SLTextStyle.GOLD) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun gray(s: String) = s.style(SLTextStyle.GRAY) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun darkGray(s: String) = s.style(SLTextStyle.DARK_GRAY) - -@Deprecated("Use Ion MiniMessage Extension Functions") -fun green(s: String) = s.style(SLTextStyle.GREEN) - @Deprecated("Use Ion MiniMessage Extension Functions") fun aqua(s: String) = s.style(SLTextStyle.AQUA) @Deprecated("Use Ion MiniMessage Extension Functions") fun red(s: String) = s.style(SLTextStyle.RED) -@Deprecated("Use Ion MiniMessage Extension Functions") -fun lightPurple(s: String) = s.style(SLTextStyle.LIGHT_PURPLE) - @Deprecated("Use Ion MiniMessage Extension Functions") fun yellow(s: String) = s.style(SLTextStyle.YELLOW) -@Deprecated("Use Ion MiniMessage Extension Functions") -fun white(s: String) = s.style(SLTextStyle.WHITE) - @Suppress("Unused") @Deprecated("Use Ion MiniMessage Extension Functions") enum class SLTextStyle(val wrappedColor: ChatColor) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Notify.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Notify.kt index 8745277679..fd6e29bc93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Notify.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Notify.kt @@ -7,7 +7,8 @@ import net.horizonsend.ion.common.database.schema.nations.Settlement import net.horizonsend.ion.common.utils.discord.Embed import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.cache.PlayerCache -import net.horizonsend.ion.server.miscellaneous.utils.Discord.asDiscord +import net.horizonsend.ion.server.features.chat.Discord +import net.horizonsend.ion.server.features.chat.Discord.asDiscord import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.litote.kmongo.id.WrappedObjectId diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Sounds.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Sounds.kt deleted file mode 100644 index 83ad558915..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Sounds.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.horizonsend.ion.server.miscellaneous.utils - -import org.bukkit.Sound -import org.bukkit.craftbukkit.CraftSound - -val Sound.mcName: String get() = CraftSound.getSound(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Vault.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Vault.kt index bb77b12f04..f7339000be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Vault.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Vault.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.miscellaneous.utils -import net.milkbowl.vault.chat.Chat import net.milkbowl.vault.economy.Economy import org.bukkit.Bukkit import org.bukkit.OfflinePlayer @@ -8,9 +7,6 @@ import org.bukkit.OfflinePlayer /** Registered vault economy service */ val VAULT_ECO: Economy = Bukkit.getServer().servicesManager.getRegistration(Economy::class.java)!!.provider -/** Registered vault permissions service */ -val vaultChat: Chat = Bukkit.getServer().servicesManager.getRegistration(Chat::class.java)!!.provider - fun OfflinePlayer.getMoneyBalance(): Double = VAULT_ECO.getBalance(this) fun OfflinePlayer.hasEnoughMoney(amount: Number): Boolean = VAULT_ECO.has(this, amount.toDouble()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt similarity index 72% rename from server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt index 490f7c0594..180755863a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/NewBlockKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt @@ -1,6 +1,5 @@ -package net.horizonsend.ion.server.miscellaneous.utils +package net.horizonsend.ion.server.miscellaneous.utils.coordinates -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.minecraft.core.BlockPos /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Position.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Position.kt similarity index 55% rename from server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Position.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Position.kt index a416432249..5ef7555045 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Position.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Position.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.miscellaneous.utils +package net.horizonsend.ion.server.miscellaneous.utils.coordinates @Deprecated("") data class Position( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt index 423a1bd02d..213db71bf3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt @@ -3,13 +3,13 @@ package net.horizonsend.ion.server.miscellaneous.utils.coordinates import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.block.BlockFace -fun toAbsolute(face: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { - val right = face.rightFace +fun toAbsolute(inwardFace: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { + val rightFace = inwardFace.rightFace return Vec3i( - x = (right.modX * leftRight) + (face.modX * backFourth), + x = rightFace.modX * leftRight + inwardFace.modX * backFourth, y = upDown, - z = (right.modZ * leftRight) + (face.modZ * backFourth) + z = rightFace.modZ * leftRight + inwardFace.modZ * backFourth ) } From 14cf098b932f0e7ff623931fe3017b16a14ed0cb Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Mar 2024 01:22:03 -0500 Subject: [PATCH 012/500] start on new extractors and power --- server/build.gradle.kts | 1 + ...werNetwork.kt => ChunkTransportNetwork.kt} | 26 ++++++++++++++----- .../features/transport/ExtractorData.kt | 10 +++---- .../extractors/PersistentExtractorData.kt | 10 +++++++ .../features/transport/grid/GridNode.kt | 5 ++++ .../features/transport/grid/PowerGrid.kt | 7 +++++ .../ion/server/features/world/IonChunk.kt | 9 ++++--- 7 files changed, 53 insertions(+), 15 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ChunkPowerNetwork.kt => ChunkTransportNetwork.kt} (56%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 4714110462..32ba0aa093 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -45,6 +45,7 @@ dependencies { compileOnly("xyz.xenondevs.invui:invui:1.43") // Downloaded via paper library manager for remapping // Included Dependencies + implementation("com.google.guava:guava:33.1.0-jre") implementation("com.manya:persistent-data-types:1.0.25") implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT") implementation("com.daveanthonythomas.moshipack:moshipack:1.0.1") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt similarity index 56% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index 81120e2964..b866cd3717 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -1,46 +1,58 @@ package net.horizonsend.ion.server.features.transport +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.server.features.multiblock.entity.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Chunk import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue -class ChunkPowerNetwork( +class ChunkTransportNetwork( val chunk: IonChunk, ) { + // Each chunk gets a scope for parallelism + private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + val extractorData = getExtractorData(chunk.inner) + val poweredMultiblockEntities = ConcurrentHashMap() + val powerGrid = PowerGrid(extractorData) + init { setup() } private fun setup() { - + collectPowerMultiblockEntities() } fun tick() { + for ((location, extractor) in extractorData.extractorLocations) { + } } fun save() { } - private fun getPowerMultiblockEntities(): ConcurrentHashMap { - val poweredMultiblockEntities = ConcurrentHashMap() + private fun tickExtractors() { + } + + private fun collectPowerMultiblockEntities() { chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> if (entity !is PoweredMultiblockEntity) return@forEach poweredMultiblockEntities[key] = entity } - - return poweredMultiblockEntities } - fun getExtractorData(chunk: Chunk): ExtractorData { + private fun getExtractorData(chunk: Chunk): ExtractorData { val extractors = chunk.persistentDataContainer.get(NamespacedKeys.EXTRACTOR_DATA, ExtractorData) return extractors ?: ExtractorData(ConcurrentLinkedQueue()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt index 0376ce2f00..daaec4defd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt @@ -10,11 +10,11 @@ import java.util.concurrent.ConcurrentLinkedQueue class ExtractorData( val extractorLocations: ConcurrentLinkedQueue ) { - companion object : PersistentDataType, ExtractorData> { - override fun getPrimitiveType(): Class> = Array::class.java + companion object : PersistentDataType { + override fun getPrimitiveType(): Class = LongArray::class.java override fun getComplexType(): Class = ExtractorData::class.java - override fun fromPrimitive(primitive: Array, context: PersistentDataAdapterContext): ExtractorData { + override fun fromPrimitive(primitive: LongArray, context: PersistentDataAdapterContext): ExtractorData { val list = ConcurrentLinkedQueue() for (key in primitive) { @@ -24,8 +24,8 @@ class ExtractorData( return ExtractorData(list) } - override fun toPrimitive(complex: ExtractorData, context: PersistentDataAdapterContext): Array { - return complex.extractorLocations.map { toBlockKey(it) }.toTypedArray() + override fun toPrimitive(complex: ExtractorData, context: PersistentDataAdapterContext): LongArray { + return complex.extractorLocations.map { toBlockKey(it) }.toLongArray() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt new file mode 100644 index 0000000000..011516e86b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.extractors + +class PersistentExtractorData( + val x: Int, + val y: Int, + val z: Int, + +) { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt new file mode 100644 index 0000000000..02346f2d02 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid + +class GridNode { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt new file mode 100644 index 0000000000..01be16b059 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.grid + +import net.horizonsend.ion.server.features.transport.ExtractorData + +class PowerGrid(private val extractorData: ExtractorData) { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 605d60e1f8..19155629ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.world import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager -import net.horizonsend.ion.server.features.transport.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener import org.bukkit.Chunk @@ -16,13 +16,16 @@ class IonChunk(val inner: Chunk) { val originX = inner.x.shl(4) val originZ = inner.z.shl(4) + val x = inner.x + val z = inner.z + // TODO // - Wires // - Ore upgrader // - Explosion Reversal val multiblockManager = ChunkMultiblockManager(this) - val powerNetwork: ChunkPowerNetwork = ChunkPowerNetwork(this) + val transportNetwork: ChunkTransportNetwork = ChunkTransportNetwork(this) /** * Logic upon loading the chunk @@ -49,7 +52,7 @@ class IonChunk(val inner: Chunk) { * Logic upon world tick **/ fun tick() { - powerNetwork.tick() + transportNetwork.tick() multiblockManager.tick() } From 445e9848d07b969f8790d07a09fa8ee130f917b8 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Mar 2024 01:34:16 -0500 Subject: [PATCH 013/500] build out some multiblock entity types --- .../multiblock/ChunkMultiblockManager.kt | 2 +- .../{ => type}/PoweredMultiblockEntity.kt | 36 +++++++------- .../entity/type/ProcessingMultiblockEntity.kt | 48 +++++++++++++++++++ .../{ => type}/TickingMultiblockEntity.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 2 +- .../transport/ChunkTransportNetwork.kt | 2 +- .../persistence/NamespacedKeys.kt | 2 + 7 files changed, 71 insertions(+), 23 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/{ => type}/PoweredMultiblockEntity.kt (63%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/{ => type}/TickingMultiblockEntity.kt (79%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 19cc462293..85843039e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt similarity index 63% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 64171e8aaf..c13e1b8ff6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -1,29 +1,18 @@ -package net.horizonsend.ion.server.features.multiblock.entity +package net.horizonsend.ion.server.features.multiblock.entity.type -import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.World -import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataType -abstract class PoweredMultiblockEntity( - type: Multiblock, - x: Int, - y: Int, - z: Int, - world: World, - signOffset: BlockFace, - private var power: Int -) : MultiblockEntity(type, x, y, z, world, signOffset) { - init { - require(type is PowerStoringMultiblock) - } - - val maxPower = (type as PowerStoringMultiblock).maxPower +interface PoweredMultiblockEntity { + var power: Int + val type: PowerStoringMultiblock - private val prefixComponent = Component.text("E: ", NamedTextColor.YELLOW) + val maxPower get() = type.maxPower fun setPower(amount: Int) { val correctedPower = amount.coerceIn(0, maxPower) @@ -70,4 +59,13 @@ abstract class PoweredMultiblockEntity( fun canRemovePower(amount: Int): Boolean { return getPower() - amount > 0 } + + companion object { + private val prefixComponent = Component.text("E: ", NamedTextColor.YELLOW) + } + + /** Store power data */ + fun storePower(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, power) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt new file mode 100644 index 0000000000..c1aefc0bfa --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -0,0 +1,48 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType + +/** + * A multiblock that handles the processing of something + * + * @param requiredProgress The number of ticks to finish this process + * @param currentProgress The current progress of the process + **/ +abstract class ProcessingMultiblockEntity( + type: Multiblock, + x: Int, + y: Int, + z: Int, + world: World, + signOffset: BlockFace, + val requiredProgress: Int, + var currentProgress: Int = 0 +) : MultiblockEntity(type, x, y, z, world, signOffset), TickingMultiblockEntity { + //TODO + // -recipe system + + abstract fun canProcess(): Boolean + abstract fun finishProcessing() + abstract fun startProcessing() + abstract fun process() + + override suspend fun tick() { + if (currentProgress >= requiredProgress) { + currentProgress = 0 + finishProcessing() + return + } + + currentProgress++ + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.PROCESSING_PROGRESS, PersistentDataType.INTEGER, currentProgress) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/TickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/TickingMultiblockEntity.kt similarity index 79% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/TickingMultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/TickingMultiblockEntity.kt index 4b4c09b625..97f775e07b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/TickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/TickingMultiblockEntity.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.entity +package net.horizonsend.ion.server.features.multiblock.entity.type /** * Any multiblock that should be ticked along with the world diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 9a98940a59..5719e5b7ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.TickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index b866cd3717..a17ec9d001 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import net.horizonsend.ion.server.features.multiblock.entity.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 0eb2d426ab..862fb4f56b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -83,6 +83,8 @@ object NamespacedKeys { val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") val EXTRACTOR_DATA = key("extractor_data") + val PROCESSING_PROGRESS = key("processing_progress") + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs From 465d9f9f3236174408baadd405fdea1553a87bbd Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Mar 2024 14:38:31 -0500 Subject: [PATCH 014/500] graphs --- .../transport/ChunkTransportNetwork.kt | 2 +- .../features/transport/grid/AbstractGrid.kt | 7 +++++ .../features/transport/grid/GridNode.kt | 12 +++++++- .../features/transport/grid/PowerGrid.kt | 7 ----- .../transport/grid/power/PowerGrid.kt | 30 +++++++++++++++++++ .../transport/grid/power/PowerNodes.kt | 14 +++++++++ 6 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index a17ec9d001..e80ee7ff20 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.power.PowerGrid import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Chunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt new file mode 100644 index 0000000000..9eda2dd39b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.grid + +import com.google.common.graph.AbstractGraph + +abstract class AbstractGrid : AbstractGraph() { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt index 02346f2d02..4703f66808 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt @@ -1,5 +1,15 @@ package net.horizonsend.ion.server.features.transport.grid -class GridNode { +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap +interface GridNode { + val x: Int + val y: Int + val z: Int + + val key get() = toBlockKey(x, y, z) + + val neighbors: ConcurrentHashMap } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt deleted file mode 100644 index 01be16b059..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import net.horizonsend.ion.server.features.transport.ExtractorData - -class PowerGrid(private val extractorData: ExtractorData) { - -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt new file mode 100644 index 0000000000..b1d1effe94 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.transport.grid.power + +import com.google.common.graph.ElementOrder +import net.horizonsend.ion.server.features.transport.ExtractorData +import net.horizonsend.ion.server.features.transport.grid.AbstractGrid + +class PowerGrid(private val extractorData: ExtractorData) : AbstractGrid() { + override fun isDirected(): Boolean = false + override fun allowsSelfLoops(): Boolean = false + + override fun successors(node: PowerNode): MutableSet { + TODO("Not yet implemented") + } + + override fun predecessors(node: PowerNode): MutableSet { + TODO("Not yet implemented") + } + + override fun nodes(): MutableSet { + TODO("Not yet implemented") + } + + override fun nodeOrder(): ElementOrder { + TODO("Not yet implemented") + } + + override fun adjacentNodes(node: PowerNode): MutableSet { + return node.neighbors.values.mapTo(mutableSetOf()) { it as PowerNode } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt new file mode 100644 index 0000000000..87f2d2694c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.transport.grid.power + +import net.horizonsend.ion.server.features.transport.grid.GridNode +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +abstract class PowerNode( + override val x: Int, + override val y: Int, + override val z: Int, + override val neighbors: ConcurrentHashMap = ConcurrentHashMap() +) : GridNode { + +} From 50fe53dbed46498620b205ea91e0b2b10b8acb26 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 18 Mar 2024 01:54:29 -0500 Subject: [PATCH 015/500] start of nodes and grids --- .../transport/ChunkTransportNetwork.kt | 2 +- .../features/transport/grid/AbstractGrid.kt | 66 ++++++++++++++++++- .../transport/grid/node/ExtractorNode.kt | 13 ++++ .../transport/grid/{ => node}/GridNode.kt | 2 +- .../transport/grid/power/PowerGrid.kt | 25 +------ .../transport/grid/power/PowerInputNode.kt | 35 ++++++++++ .../transport/grid/power/PowerNodes.kt | 2 +- .../ion/server/features/world/IonChunk.kt | 4 ++ 8 files changed, 120 insertions(+), 29 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{ => node}/GridNode.kt (82%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index e80ee7ff20..64a8e3ffb3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -15,7 +15,7 @@ class ChunkTransportNetwork( val chunk: IonChunk, ) { // Each chunk gets a scope for parallelism - private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) val extractorData = getExtractorData(chunk.inner) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt index 9eda2dd39b..db18aa8de6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt @@ -1,7 +1,69 @@ package net.horizonsend.ion.server.features.transport.grid -import com.google.common.graph.AbstractGraph +import kotlinx.coroutines.Job +import kotlinx.coroutines.joinAll +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.minecraft.world.level.chunk.LevelChunkSection +import org.bukkit.block.Block +import java.util.concurrent.ConcurrentHashMap -abstract class AbstractGrid : AbstractGraph() { +abstract class AbstractGrid(val network: ChunkTransportNetwork) { + val nodes: ConcurrentHashMap = ConcurrentHashMap() + val grids: Nothing = TODO("Grid system") + + /** + * + **/ + abstract fun isNode(block: Block): Boolean + + // TODO maybe move this to a member function of grid node + abstract fun shouldConsolidate(node: GridNode) + + /** + * Builds the grid TODO better documentation + **/ + fun build() = network.scope.launch { + collectAllNodes().join() + consolidateNodes() + buildGraph() + } + + /** + * + **/ + private fun collectAllNodes(): Job = network.scope.launch { + // Parallel collect the nodes of each section + network.chunk.sections.map { (y, section) -> + launch { collectSectionNodes(y, section) } + }.joinAll() + } + + /** + * Collect all nodes in this chunk section + **/ + fun collectSectionNodes(sectionY: Int, section: LevelChunkSection) { + for (x: Int in 0..15) for (y: Int in 0..15) for (z: Int in 0..15) { + val key = toBlockKey(x, y, z) + } + } + + /** + * Consolidates network nodes where possible + * + * e.g. a straight section may be represented as a single node + **/ + fun consolidateNodes() { + + } + + /** + * + **/ + fun buildGraph() { + + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt new file mode 100644 index 0000000000..4508e7a9b0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.transport.grid.node + +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class ExtractorNode( + override val x: Int, + override val y: Int, + override val z: Int, + override val neighbors: ConcurrentHashMap = ConcurrentHashMap() +) : GridNode { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt similarity index 82% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt index 4703f66808..da8fa7d28d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.grid +package net.horizonsend.ion.server.features.transport.grid.node import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt index b1d1effe94..1581ceb11c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt @@ -1,30 +1,7 @@ package net.horizonsend.ion.server.features.transport.grid.power -import com.google.common.graph.ElementOrder import net.horizonsend.ion.server.features.transport.ExtractorData -import net.horizonsend.ion.server.features.transport.grid.AbstractGrid -class PowerGrid(private val extractorData: ExtractorData) : AbstractGrid() { - override fun isDirected(): Boolean = false - override fun allowsSelfLoops(): Boolean = false +class PowerGrid(private val extractorData: ExtractorData) { - override fun successors(node: PowerNode): MutableSet { - TODO("Not yet implemented") - } - - override fun predecessors(node: PowerNode): MutableSet { - TODO("Not yet implemented") - } - - override fun nodes(): MutableSet { - TODO("Not yet implemented") - } - - override fun nodeOrder(): ElementOrder { - TODO("Not yet implemented") - } - - override fun adjacentNodes(node: PowerNode): MutableSet { - return node.neighbors.values.mapTo(mutableSetOf()) { it as PowerNode } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt new file mode 100644 index 0000000000..10023ec216 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt @@ -0,0 +1,35 @@ +package net.horizonsend.ion.server.features.transport.grid.power + +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class PowerInputNode( + x: Int, + y: Int, + z: Int, + neighbors: ConcurrentHashMap = ConcurrentHashMap() +) : PowerNode(x, y, z, neighbors) { + /** + * Gets the multiblocks to which this can input power + **/ + suspend fun getMultiblocks(): Collection = TODO() + + companion object { + /** + * The offsets at which a multiblock sign might be found. + **/ + private val offsets = setOf( + // most multiblocks have the sign a block up and out of the computer + Vec3i(1, 1, 0), Vec3i(-1, 1, 0), Vec3i(0, 1, -1), Vec3i(0, 1, 1), + // power cells have it on the block + Vec3i(1, 0, 0), Vec3i(-1, 0, 0), Vec3i(0, 0, -1), Vec3i(0, 0, 1), + // drills have it on a corner + Vec3i(-1, 0, -1), Vec3i(1, 0, -1), Vec3i(1, 0, 1), Vec3i(-1, 0, 1), + // upside down mining lasers have signs below + Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), + ) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt index 87f2d2694c..e0c80884dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.grid.power -import net.horizonsend.ion.server.features.transport.grid.GridNode +import net.horizonsend.ion.server.features.transport.grid.node.GridNode import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 19155629ca..0f5a407e98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -4,6 +4,8 @@ import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.world.level.chunk.LevelChunkSection import org.bukkit.Chunk import org.bukkit.World import org.bukkit.event.EventHandler @@ -19,6 +21,8 @@ class IonChunk(val inner: Chunk) { val x = inner.x val z = inner.z + val sections: Iterable> get() = inner.minecraft.sections.withIndex() + // TODO // - Wires // - Ore upgrader From 4079d1aa2f0f6ea17054c874375fb7712d48b6df Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 18 Mar 2024 14:28:16 -0500 Subject: [PATCH 016/500] node collection and straight wire consolidation --- .../features/multiblock/util/BlockSnapshot.kt | 18 ++++- .../features/transport/grid/AbstractGrid.kt | 70 +++++++++++++++---- .../transport/grid/node/ExtractorNode.kt | 2 +- .../features/transport/grid/node/GridNode.kt | 22 ++++++ .../transport/grid/node/JunctionNode.kt | 5 ++ .../transport/grid/node/StraightNode.kt | 62 ++++++++++++++++ .../transport/grid/power/PowerInputNode.kt | 2 +- .../ion/server/features/world/IonChunk.kt | 6 ++ .../ion/server/miscellaneous/utils/Blocks.kt | 6 ++ 9 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt index d835b27a21..af85db0218 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt @@ -1,11 +1,23 @@ package net.horizonsend.ion.server.features.multiblock.util +import kotlinx.coroutines.runBlocking +import org.bukkit.Bukkit import org.bukkit.ChunkSnapshot import org.bukkit.Material +import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.BlockState import org.bukkit.block.data.BlockData -class BlockSnapshot(val x: Int, val y: Int, val z: Int, val type: Material, val data: BlockData) { +class BlockSnapshot(val world: World, val x: Int, val y: Int, val z: Int, val type: Material, val data: BlockData) { + val state: BlockState? get() { + return runBlocking { getBukkitBlockState(block, false) } + } + + val block: Block get() { + return world.getBlockAt(x, y, z) + } + companion object { fun ChunkSnapshot.getBlockSnapshot(x: Int, y: Int, z: Int): BlockSnapshot? { if (x shr 4 != getX()) return null @@ -17,9 +29,9 @@ class BlockSnapshot(val x: Int, val y: Int, val z: Int, val type: Material, val val localX = x - chunkOriginX val localZ = z - chunkOriginZ - return BlockSnapshot(x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) + return BlockSnapshot(Bukkit.getWorld(worldName)!!, x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) } - fun Block.snapshot(): BlockSnapshot = BlockSnapshot(x, y, z, type, blockData) + fun Block.snapshot(): BlockSnapshot = BlockSnapshot(world, x, y, z, type, blockData) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt index db18aa8de6..3cdfc20529 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt @@ -3,11 +3,12 @@ package net.horizonsend.ion.server.features.transport.grid import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.minecraft.world.level.chunk.LevelChunkSection -import org.bukkit.block.Block import java.util.concurrent.ConcurrentHashMap abstract class AbstractGrid(val network: ChunkTransportNetwork) { @@ -18,7 +19,14 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { /** * **/ - abstract fun isNode(block: Block): Boolean + abstract fun isNode(block: BlockSnapshot): Boolean + + /** + * Handle the creation / loading of the node into memory + * + * Inheritors may choose to save persistent data, or not + **/ + abstract fun loadNode(block: BlockSnapshot): GridNode? // TODO maybe move this to a member function of grid node abstract fun shouldConsolidate(node: GridNode) @@ -37,17 +45,55 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { **/ private fun collectAllNodes(): Job = network.scope.launch { // Parallel collect the nodes of each section - network.chunk.sections.map { (y, section) -> - launch { collectSectionNodes(y, section) } + network.chunk.sections.map { (y, _) -> + launch { collectSectionNodes(y) } }.joinAll() } /** * Collect all nodes in this chunk section + * + * Iterate the section for possible nodes, handle creation **/ - fun collectSectionNodes(sectionY: Int, section: LevelChunkSection) { - for (x: Int in 0..15) for (y: Int in 0..15) for (z: Int in 0..15) { - val key = toBlockKey(x, y, z) + suspend fun collectSectionNodes(sectionY: Int) { + val originX = network.chunk.originX + val originY = sectionY.shl(4) - network.chunk.inner.world.minHeight + val originZ = network.chunk.originZ + + for (x: Int in 0..15) { + val realX = originX + x + + for (y: Int in 0..15) { + val realY = originY + y + + for (z: Int in 0..15) { + val realZ = originZ + z + + val snapshot = getBlockSnapshotAsync(network.chunk.world, realX, realY, realZ) ?: continue + + if (!isNode(snapshot)) continue + + val node = loadNode(snapshot) ?: continue + + nodes[toBlockKey(realX, realY, realZ)] = node + collectNeighbors(node) + } + } + } + } + + /** + * Get the neighbors of a node + **/ + private fun collectNeighbors(node: GridNode) { + for (direction in ADJACENT_BLOCK_FACES) { + val newX = node.x + direction.modX + val newY = node.y + direction.modY + val newZ = node.z + direction.modZ + + val possibleNode = nodes[toBlockKey(newX, newY, newZ)] ?: continue + + node.neighbors[direction] = possibleNode } } @@ -56,14 +102,14 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { * * e.g. a straight section may be represented as a single node **/ - fun consolidateNodes() { - + private fun consolidateNodes() { + //TODO } /** * **/ - fun buildGraph() { - + private fun buildGraph() { + //TODO } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt index 4508e7a9b0..c0cb8503e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.grid.node import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -class ExtractorNode( +abstract class ExtractorNode( override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt index da8fa7d28d..1e07e240b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt @@ -1,10 +1,12 @@ package net.horizonsend.ion.server.features.transport.grid.node +import net.horizonsend.ion.server.features.transport.grid.AbstractGrid import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap interface GridNode { + val parent: AbstractGrid val x: Int val y: Int val z: Int @@ -12,4 +14,24 @@ interface GridNode { val key get() = toBlockKey(x, y, z) val neighbors: ConcurrentHashMap + + fun getNeighbor(face: BlockFace): GridNode? { + return neighbors[face] + } + + /** + * Consolidates this node if possible + **/ + fun consolidate() + + /** + * Replace this node with another and update its neighbors + **/ + fun replace(new: GridNode) { + for ((offset, neighbor) in neighbors) { + val neighborRelation = offset.oppositeFace + + neighbor.neighbors[neighborRelation] = neighbor + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt new file mode 100644 index 0000000000..1e8c4409be --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid.node + +abstract class JunctionNode : GridNode { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt new file mode 100644 index 0000000000..fec169fcd3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt @@ -0,0 +1,62 @@ +package net.horizonsend.ion.server.features.transport.grid.node + +import net.horizonsend.ion.server.features.transport.grid.AbstractGrid +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_PAIRS +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +/** + * Represents a straight connection, e.g. wire, glass pane + * + * @param positions The keys of the positions that this straight node occupies + **/ +class StraightNode( + override val parent: AbstractGrid, + override val x: Int, + override val y: Int, + override val z: Int, + override val neighbors: ConcurrentHashMap = ConcurrentHashMap(), + val positions: Set +) : GridNode { + override fun consolidate() { + // Check neighbors in straight line + for (adjacentPairs in ADJACENT_PAIRS) { + if (!adjacentPairs.all { + getNeighbor(it) is StraightNode + }) continue + + val neighborNodes = adjacentPairs.mapNotNull(::getNeighbor) + + // Keys of all 3 + val occupiedKeys = neighborNodes.mapTo(mutableSetOf()) { it.key }.plus(key) + + // Add all the merged neighbors together + val newNeighborsList = ConcurrentHashMap() + neighborNodes.mapTo(mutableListOf()) { it.neighbors }.plus(neighbors).forEach(newNeighborsList::putAll) + + // Create a new node representing a single straight connection between all + val new = StraightNode( + parent, + x, y, z, + newNeighborsList, + occupiedKeys + ) + + // Replace the neighbor positions with the new straight one and update neighbor relations + neighborNodes.forEach { node -> + val key = node.key + + parent.nodes[key] = new + + node.replace(new) + } + + // Replace this one + parent.nodes[key] = new + replace(new) + + // Only merge once + return + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt index 10023ec216..613cb517e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -class PowerInputNode( +abstract class PowerInputNode( x: Int, y: Int, z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 0f5a407e98..f1b148069b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -15,12 +15,18 @@ import org.bukkit.event.world.ChunkUnloadEvent class IonChunk(val inner: Chunk) { val locationKey = inner.chunkKey + /** The origin X coordinate of this chunk (in real coordinates) **/ val originX = inner.x.shl(4) + /** The origin Z coordinate of this chunk (in real coordinates) **/ val originZ = inner.z.shl(4) + /** The X chunk coordinate **/ val x = inner.x + /** The Z chunk coordinate **/ val z = inner.z + val world get() = inner.world + val sections: Iterable> get() = inner.minecraft.sections.withIndex() // TODO diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index 5b00f0a838..d98365c5d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -80,6 +80,12 @@ val ADJACENT_BLOCK_FACES: Set = ImmutableSet.of( BlockFace.DOWN ) +val ADJACENT_PAIRS: Set> = ImmutableSet.of( + ImmutableSet.of(BlockFace.NORTH, BlockFace.SOUTH), + ImmutableSet.of(BlockFace.EAST, BlockFace.WEST), + ImmutableSet.of(BlockFace.NORTH, BlockFace.SOUTH) +) + val CARDINAL_BLOCK_FACES: Set = ImmutableSet.of( BlockFace.NORTH, BlockFace.SOUTH, From 186c7661334683847b8995b65a891f04344e3c21 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 22 Mar 2024 23:04:57 -0500 Subject: [PATCH 017/500] work on grids --- .../multiblock/ChunkMultiblockManager.kt | 4 +- .../server/features/multiblock/Multiblock.kt | 5 +- .../server/features/multiblock/Multiblocks.kt | 448 ++++++++++-------- .../multiblock/type/InteractableMultiblock.kt | 2 +- .../transport/ChunkTransportNetwork.kt | 32 +- .../transport/container/ItemContainer.kt | 4 + .../container/NamespacedResourceContainer.kt | 169 +++++++ .../transport/container/ResourceContainer.kt | 28 ++ .../features/transport/grid/AbstractGrid.kt | 13 +- .../transport/grid/NamespaceTransferGrid.kt | 19 + .../features/transport/grid/PowerGrid.kt | 46 ++ .../transport/grid/node/JunctionNode.kt | 14 +- .../features/transport/grid/node/NodeType.kt | 7 + .../transport/grid/node/StraightNode.kt | 2 +- .../transport/grid/node/power/GrabbyNode.kt | 4 + .../grid/node/power/PowerExtractorNode.kt | 4 + .../grid/{ => node}/power/PowerInputNode.kt | 2 +- .../transport/grid/node/power/PowerNodes.kt | 3 + .../transport/grid/power/PowerGrid.kt | 7 - .../transport/grid/power/PowerNodes.kt | 14 - .../persistence/NamespacedKeys.kt | 4 + 21 files changed, 571 insertions(+), 260 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{ => node}/power/PowerInputNode.kt (94%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 85843039e8..616d86ca93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -49,7 +49,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { private fun handleMultiblockTick(multiblock: TickingMultiblockEntity): Boolean = try { if (multiblock.tickAsync) { - Multiblocks.context.launch { multiblock.tick() } + Multiblocks.multiblockCoroutineScope.launch { multiblock.tick() } } else runBlocking { multiblock.tick() } true @@ -103,7 +103,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { /** * Save the multiblock data back into the chunk **/ - private fun saveMultiblocks() = Multiblocks.context.launch { + private fun saveMultiblocks() = Multiblocks.multiblockCoroutineScope.launch { val array = multiblockEntities.map { (_, entity) -> PersistentMultiblockData.toPrimitive(entity.store(), chunk.inner.persistentDataContainer.adapterContext) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 3857bd5219..506c3e0fc1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -15,6 +15,7 @@ import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.type.WallSign +import org.bukkit.block.sign.Side import org.bukkit.entity.Player abstract class Multiblock { @@ -106,7 +107,9 @@ abstract class Multiblock { } open fun matchesUndetectedSign(sign: Sign): Boolean { - return (sign.line(0) as TextComponent).content().equals("[$name]", ignoreCase = true) + return (sign.getSide(Side.FRONT).line(0) as TextComponent) + .content() + .equals("[$name]", ignoreCase = true) } open fun setupSign(player: Player, sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 945a06114a..e50e0c615b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -76,7 +76,6 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirloc import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.LargeTractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock @@ -152,6 +151,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.isSign import org.bukkit.World import org.bukkit.block.Sign +import org.bukkit.block.sign.Side import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority @@ -165,185 +165,235 @@ import java.util.UUID object Multiblocks : IonServerComponent() { private val multiblocks: MutableMap = mutableMapOf() + val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + + override fun onEnable() { + initMultiblocks() + + log.info("Loaded ${multiblocks.size} multiblocks") + } private fun initMultiblocks() { - multiblocks.putAll(listOf( - CentrifugeMultiblock, - CompressorMultiblock, - FabricatorMultiblock, - CircuitfabMultiblock, - PlatePressMultiblock, - GasFurnaceMultiblock, - - GeneratorMultiblockTier1, - GeneratorMultiblockTier2, - GeneratorMultiblockTier3, - - PowerFurnaceMultiblockTier1, - PowerFurnaceMultiblockTier2, - PowerFurnaceMultiblockTier3, - - PowerBankMultiblockTier1, - PowerBankMultiblockTier2, - PowerBankMultiblockTier3, - - PowerCellMultiblock, - - ChargerMultiblockTier1, - ChargerMultiblockTier2, - ChargerMultiblockTier3, - - HyperdriveMultiblockClass1, - HyperdriveMultiblockClass2, - HyperdriveMultiblockClass3, - HyperdriveMultiblockClass4, - - NavigationComputerMultiblockBasic, - VerticalNavigationComputerMultiblockAdvanced, - HorizontalNavigationComputerMultiblockAdvanced, - - ShieldMultiblockClass08Right, - ShieldMultiblockClass08Left, - ShieldMultiblockClass20, - ShieldMultiblockClass30, - ShieldMultiblockClass65, - ShieldMultiblockClass85, - ShieldMultiblockClass08i, - BoxShieldMultiblock, - EventShieldMultiblock, - - CarbonProcessorMultiblock, - - CarbonPrinterMultiblock, - TechnicalPrinterMultiblock, - GlassPrinterMultiblock, - ArmorPrinterMultiblock, - - DisconnectedDockingTubeMultiblock, - ConnectedDockingTubeMultiblock, - - CryoPodMultiblock, - FuelTankMultiblock, - MagazineMultiblock, - AirlockMultiblock, - ExpandableAirlock, - TractorBeamMultiblock, - LargeTractorBeamMultiblock, - - ShipFactoryMultiblock, - - DrillMultiblockTier1, - DrillMultiblockTier2, - DrillMultiblockTier3, - - StandardGravityWellMultiblock, - AmplifiedGravityWellMultiblock, - - AreaShield5, - AreaShield10, - AreaShield20, - AreaShield30, - - MobDefender, - - StandardAmmoPressMultiblock, - AmmoLoaderMultiblock, - MissileLoaderMultiblock, - - LaserCannonStarshipWeaponMultiblock, - PlasmaCannonStarshipWeaponMultiblock, - PulseCannonStarshipWeaponMultiblock, - HeavyLaserStarshipWeaponMultiblock, - AIHeavyLaserStarshipWeaponMultiblock, - AIPhaserStarshipWeaponMultiblock, - TorpedoStarshipWeaponMultiblock, - PointDefenseStarshipWeaponMultiblockTop, - PointDefenseStarshipWeaponMultiblockSide, - PointDefenseStarshipWeaponMultiblockBottom, - TopLightTurretMultiblock, - BottomLightTurretMultiblock, - TopHeavyTurretMultiblock, - BottomHeavyTurretMultiblock, - TopTriTurretMultiblock, - BottomTriTurretMultiblock, - TopIonTurretMultiblock, - BottomIonTurretMultiblock, - TopQuadTurretMultiblock, - BottomQuadTurretMultiblock, - HorizontalRocketStarshipWeaponMultiblock, - UpwardRocketStarshipWeaponMultiblock, - DownwardRocketStarshipWeaponMultiblock, - PhaserStarshipWeaponMultiblock, - MiniPhaserStarshipWeaponMultiblock, - SonicMissileWeaponMultiblock, - DecomposerMultiblock, - DisposalMultiblock, - MiningLaserMultiblockTier1Top, - MiningLaserMultiblockTier1Bottom, - MiningLaserMultiblockTier1Side, - MiningLaserMultiblockTier2Top, - MiningLaserMultiblockTier2Bottom, - MiningLaserMultiblockTier2Side, - MiningLaserMultiblockTier3Top, - MiningLaserMultiblockTier3Bottom, - MiningLaserMultiblockTier3Side, - MiningLaserMultiblockTier4Top, - MiningLaserMultiblockTier4Bottom, - MiningLaserMultiblockTier4Side, - TopArsenalStarshipWeaponMultiblock, - BottomArsenalStarshipWeaponMultiblock, - - ItemSplitterMultiblock, - GasCollectorMultiblock, - GasPowerPlantMultiblock, - VentMultiblock, - - LandingGearMultiblock, - - AutoCrafterMultiblockTier1, - AutoCrafterMultiblockTier2, - AutoCrafterMultiblockTier3, - - HorizontalPumpkinCannonStarshipWeaponMultiblock, - CthulhuBeamStarshipWeaponMultiblockBottom, - CthulhuBeamStarshipWeaponMultiblockTop, - CthulhuBeamStarshipWeaponMultiblockSide, - FlamethrowerStarshipWeaponMultiblock, - CapitalBeamStarshipWeaponMultiblock, - - PlanterMultiblockTier1, - PlanterMultiblockTier2, - PlanterMultiblockTier3, - HarvesterMultiblockTier1, - HarvesterMultiblockTier2, - HarvesterMultiblockTier3, - - AntiAirCannonBaseMultiblock, -// AntiAirCannonTurretMultiblock, - - BattleCruiserReactorMultiblock, - CruiserReactorMultiblock, - BargeReactorMultiBlock, - OdometerMultiblock, - TestMultiblock - ).associateBy { it.javaClass.simpleName }) + registerMultiblock(CentrifugeMultiblock) + registerMultiblock(CompressorMultiblock) + registerMultiblock(FabricatorMultiblock) + registerMultiblock(CircuitfabMultiblock) + registerMultiblock(PlatePressMultiblock) + registerMultiblock(GasFurnaceMultiblock) + + registerMultiblock(GeneratorMultiblockTier1) + registerMultiblock(GeneratorMultiblockTier2) + registerMultiblock(GeneratorMultiblockTier3) + + registerMultiblock(PowerFurnaceMultiblockTier1) + registerMultiblock(PowerFurnaceMultiblockTier2) + registerMultiblock(PowerFurnaceMultiblockTier3) + + registerMultiblock(PowerBankMultiblockTier1) + registerMultiblock(PowerBankMultiblockTier2) + registerMultiblock(PowerBankMultiblockTier3) + + registerMultiblock(PowerCellMultiblock) + registerMultiblock(ChargerMultiblockTier1) + registerMultiblock(ChargerMultiblockTier2) + registerMultiblock(ChargerMultiblockTier3) + + registerMultiblock(HyperdriveMultiblockClass1) + registerMultiblock(HyperdriveMultiblockClass2) + registerMultiblock(HyperdriveMultiblockClass3) + registerMultiblock(HyperdriveMultiblockClass4) + + registerMultiblock(NavigationComputerMultiblockBasic) + registerMultiblock(VerticalNavigationComputerMultiblockAdvanced) + registerMultiblock(HorizontalNavigationComputerMultiblockAdvanced) + + registerMultiblock(ShieldMultiblockClass08Right) + registerMultiblock(ShieldMultiblockClass08Left) + registerMultiblock(ShieldMultiblockClass20) + registerMultiblock(ShieldMultiblockClass30) + registerMultiblock(ShieldMultiblockClass65) + registerMultiblock(ShieldMultiblockClass85) + registerMultiblock(ShieldMultiblockClass08i) + registerMultiblock(BoxShieldMultiblock) + registerMultiblock(EventShieldMultiblock) + + registerMultiblock(CarbonProcessorMultiblock) + + registerMultiblock(CarbonPrinterMultiblock) + registerMultiblock(TechnicalPrinterMultiblock) + registerMultiblock(GlassPrinterMultiblock) + registerMultiblock(ArmorPrinterMultiblock) + + registerMultiblock(DisconnectedDockingTubeMultiblock) + registerMultiblock(ConnectedDockingTubeMultiblock) + + registerMultiblock(CryoPodMultiblock) + registerMultiblock(FuelTankMultiblock) + registerMultiblock(MagazineMultiblock) + registerMultiblock(AirlockMultiblock) + registerMultiblock(ExpandableAirlock) + registerMultiblock(TractorBeamMultiblock) + + registerMultiblock(ShipFactoryMultiblock) + + registerMultiblock(DrillMultiblockTier1) + registerMultiblock(DrillMultiblockTier2) + registerMultiblock(DrillMultiblockTier3) + + registerMultiblock(StandardGravityWellMultiblock) + registerMultiblock(AmplifiedGravityWellMultiblock) + + registerMultiblock(AreaShield5) + registerMultiblock(AreaShield10) + registerMultiblock(AreaShield20) + registerMultiblock(AreaShield30) + + registerMultiblock(MobDefender) + + registerMultiblock(StandardAmmoPressMultiblock) + registerMultiblock(AmmoLoaderMultiblock) + registerMultiblock(MissileLoaderMultiblock) + + registerMultiblock(LaserCannonStarshipWeaponMultiblock) + registerMultiblock(PlasmaCannonStarshipWeaponMultiblock) + registerMultiblock(PulseCannonStarshipWeaponMultiblock) + registerMultiblock(HeavyLaserStarshipWeaponMultiblock) + registerMultiblock(AIHeavyLaserStarshipWeaponMultiblock) + registerMultiblock(AIPhaserStarshipWeaponMultiblocK) + registerMultiblock(TorpedoStarshipWeaponMultiblock) + registerMultiblock(PointDefenseStarshipWeaponMultiblockTop) + registerMultiblock(PointDefenseStarshipWeaponMultiblockSide) + registerMultiblock(PointDefenseStarshipWeaponMultiblockBottom) + registerMultiblock(TopLightTurretMultiblock) + registerMultiblock(BottomLightTurretMultiblock) + registerMultiblock(TopHeavyTurretMultiblock) + registerMultiblock(BottomHeavyTurretMultiblock) + registerMultiblock(TopTriTurretMultiblock) + registerMultiblock(BottomTriTurretMultiblock) + registerMultiblock(TopIonTurretMultiblock) + registerMultiblock(BottomIonTurretMultiblock) + registerMultiblock(TopQuadTurretMultiblock) + registerMultiblock(BottomQuadTurretMultiblock) + registerMultiblock(HorizontalRocketStarshipWeaponMultiblock) + registerMultiblock(UpwardRocketStarshipWeaponMultiblock) + registerMultiblock(DownwardRocketStarshipWeaponMultiblock) + registerMultiblock(PhaserStarshipWeaponMultiblock) + registerMultiblock(MiniPhaserStarshipWeaponMultiblock) + registerMultiblock(SonicMissileWeaponMultiblock) + registerMultiblock(DecomposerMultiblock) + registerMultiblock(DisposalMultiblock) + registerMultiblock(MiningLaserMultiblockTier1Top) + registerMultiblock(MiningLaserMultiblockTier1Bottom) + registerMultiblock(MiningLaserMultiblockTier1Side) + registerMultiblock(MiningLaserMultiblockTier2Top) + registerMultiblock(MiningLaserMultiblockTier2Bottom) + registerMultiblock(MiningLaserMultiblockTier2Side) + registerMultiblock(MiningLaserMultiblockTier3Top) + registerMultiblock(MiningLaserMultiblockTier3Bottom) + registerMultiblock(MiningLaserMultiblockTier3Side) + registerMultiblock(MiningLaserMultiblockTier4Top) + registerMultiblock(MiningLaserMultiblockTier4Bottom) + registerMultiblock(MiningLaserMultiblockTier4Side) + + registerMultiblock(ItemSplitterMultiblock) + registerMultiblock(GasCollectorMultiblock) + registerMultiblock(GasPowerPlantMultiblock) + registerMultiblock(VentMultiblock) + + registerMultiblock(LandingGearMultiblock) + + registerMultiblock(AutoCrafterMultiblockTier1) + registerMultiblock(AutoCrafterMultiblockTier2) + registerMultiblock(AutoCrafterMultiblockTier3) + + registerMultiblock(HorizontalPumpkinCannonStarshipWeaponMultiblock) + registerMultiblock(CthulhuBeamStarshipWeaponMultiblockBottom) + registerMultiblock(CthulhuBeamStarshipWeaponMultiblockTop) + registerMultiblock(CthulhuBeamStarshipWeaponMultiblockSide) + registerMultiblock(FlamethrowerStarshipWeaponMultiblock) + registerMultiblock(CapitalBeamStarshipWeaponMultiblock) + + registerMultiblock(PlanterMultiblockTier1) + registerMultiblock(PlanterMultiblockTier2) + registerMultiblock(PlanterMultiblockTier3) + registerMultiblock(HarvesterMultiblockTier1) + registerMultiblock(HarvesterMultiblockTier2) + registerMultiblock(HarvesterMultiblockTier3) + + registerMultiblock(AntiAirCannonBaseMultiblock) + registerMultiblock(BattleCruiserReactorMultiblock) + registerMultiblock(CruiserReactorMultiblock) + registerMultiblock(BargeReactorMultiBlock) + registerMultiblock(OdometerMultiblock) + registerMultiblock(TestMultiblock) + } + + private fun registerMultiblock(multiblock: Multiblock) { + val name = multiblock.javaClass.simpleName ?: throw IllegalArgumentException("Provided anonymous multiblock class!") + + if (multiblocks.containsKey(name)) { + throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[name]}, new: $multiblock") + } + + multiblocks[name] = multiblock + } + + private fun registerAlternateName(name: String, multiblock: Multiblock) { + if (multiblocks.containsKey(name)) { + throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[name]}, new: $multiblock") + } + + multiblocks[name] = multiblock } - val context = CoroutineScope(Dispatchers.Default + SupervisorJob()) + // Access /** - * Map of world UUIDs to a map of block keys to Multiblock types + * Get a multiblock by its identifying name **/ - private val newMultiblockCache: MutableMap> = Object2ObjectOpenHashMap() + fun getMultiblockByName(name: String): Multiblock = multiblocks[name]!! - override fun onEnable() { - initMultiblocks() + /** Check if a sign has been registered as a multiblock, if so, return that value */ + fun getFromPDC(sign: Sign): Multiblock? { + return getFromPDC(sign.persistentDataContainer) + } - log.info("Loaded ${multiblocks.size} multiblocks") + /** Check if a pdc, if so, return that value */ + fun getFromPDC(pdc: PersistentDataContainer): Multiblock? { + val data = pdc.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return null + + return getMultiblockByName(data) } + /** + * Get all registered multiblocks + **/ fun all(): List = multiblocks.values.toList() + // End access + + /** + * Map of world UUIDs to a map of block keys to Multiblock types + * + * - world + * |- blockKey to Multiblock + **/ + private val multiblockLocationCache: MutableMap> = Object2ObjectOpenHashMap() + + /** + * Get a previously found multiblock at this location + **/ + fun getCached(world: World, x: Int, y: Int, z: Int): Multiblock? { + return getCached(world, toBlockKey(x, y, z)) + } + + /** + * Get a previously found multiblock at this location + **/ + fun getCached(world: World, key: Long): Multiblock? { + return multiblockLocationCache.getOrPut(world.uid) { Object2ObjectOpenHashMap() }[key] + } + /** * Get a multiblock from the sign **/ @@ -358,11 +408,6 @@ object Multiblocks : IonServerComponent() { getFromSignPosition(world, x, y, z, checkStructure, loadChunks) } - /** - * Get a multiblock by its identifying name - **/ - operator fun get(name: String) = multiblocks[name] - /** * Checks against the multiblock cache for a multiblock at a position * @@ -379,7 +424,7 @@ object Multiblocks : IonServerComponent() { for ((name, multiblock) in multiblocks) { if (!matchesPersistentDataContainer(sign.persistentDataContainer, multiblock)) { - if (!multiblock.matchesSign(sign.lines())) continue else Tasks.sync { + if (!multiblock.matchesSign(sign.getSide(Side.FRONT).lines())) continue else Tasks.sync { sign.persistentDataContainer.set( NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, @@ -402,7 +447,7 @@ object Multiblocks : IonServerComponent() { * Checks against the multiblock cache for a multiblock at a position **/ private suspend fun checkCache(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean, loadChunks: Boolean): Multiblock? { - val worldCache = newMultiblockCache[world.uid] ?: return null + val worldCache = multiblockLocationCache[world.uid] ?: return null val key = toBlockKey(x, y, z) @@ -413,13 +458,7 @@ object Multiblocks : IonServerComponent() { return possibleMultiblock } - fun getFromPDC(sign: Sign): Multiblock? { - val pdc = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return null - - return multiblocks[pdc] - } - - fun matchesPersistentDataContainer(persistentDataContainer: PersistentDataContainer, multiblock: Multiblock): Boolean { + private fun matchesPersistentDataContainer(persistentDataContainer: PersistentDataContainer, multiblock: Multiblock): Boolean { val value = persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return false return value == multiblock::class.simpleName @@ -429,13 +468,10 @@ object Multiblocks : IonServerComponent() { * The check for when someone right-clicks an undetected multiblock **/ @EventHandler(priority = EventPriority.HIGHEST) - fun onInteractMultiblockSign(event: PlayerInteractEvent) = context.launch { - if (event.hand != EquipmentSlot.HAND || event.action != Action.RIGHT_CLICK_BLOCK) { - return@launch - } + fun tryDetectMultiblock(event: PlayerInteractEvent) = multiblockCoroutineScope.launch { + if (event.hand != EquipmentSlot.HAND || event.action != Action.RIGHT_CLICK_BLOCK) return@launch val clickedBlock = event.clickedBlock ?: return@launch - val sign = getBukkitBlockState(clickedBlock, false) as? Sign ?: return@launch // Don't bother checking detected multiblocks @@ -449,27 +485,24 @@ object Multiblocks : IonServerComponent() { return@launch } - // Check all multiblocks - for ((_, multiblock) in multiblocks) { - // If it has the same sign text as the multiblock - if (multiblock.matchesUndetectedSign(sign)) { - // And is built properly - if (multiblock.signMatchesStructure(sign, particles = true)) { - // Check permissions here because different tiers might have the same text - multiblock.requiredPermission?.let { - if (!player.hasPermission(it)) player.userError("You don't have permission to use that multiblock!") - return@launch - } - - // Update everything that needs to be done sync - createNewMultiblock(multiblock, sign, event.player) - + // Check all multiblocks with a matching undetected sign + for ((_, multiblock) in multiblocks.filterValues { it.matchesUndetectedSign(sign) }) { + // And is built properly + if (multiblock.signMatchesStructure(sign, particles = true)) { + // Check permissions here because different tiers might have the same text + multiblock.requiredPermission?.let { + if (!player.hasPermission(it)) player.userError("You don't have permission to use that multiblock!") return@launch - } else { - // Store the multi that last matched sign text - lastMatch = multiblock } + + // Update everything that needs to be done sync + createNewMultiblock(multiblock, sign, event.player) + + return@launch } + + // Store the multi that last matched sign text + lastMatch = multiblock } if (lastMatch != null) { @@ -481,8 +514,7 @@ object Multiblocks : IonServerComponent() { } @EventHandler - fun onPlayerBreakBlock(event: BlockBreakEvent) = context.launch { - val player = event.player + fun onPlayerBreakBlock(event: BlockBreakEvent) = multiblockCoroutineScope.launch { if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return@launch val sign = getBukkitBlockState(event.block, false) as? Sign ?: return@launch @@ -496,7 +528,7 @@ object Multiblocks : IonServerComponent() { loadChunks = false ) ?: return@launch - removeMultiblock(multiblock, sign, player) + removeMultiblock(multiblock, sign) } /** @@ -535,7 +567,7 @@ object Multiblocks : IonServerComponent() { } /** Upon a multiblock being removed */ - fun removeMultiblock(multiblock: Multiblock, sign: Sign, player: Player) = Tasks.sync { + fun removeMultiblock(multiblock: Multiblock, sign: Sign) = Tasks.sync { val (x, y, z) = Multiblock.getOrigin(sign) val chunkX = x.shr(4) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt index ff9dc19a33..a86b323fda 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt @@ -17,7 +17,7 @@ interface InteractableMultiblock { companion object : SLEventListener() { @EventHandler - fun onPlayerInteract(event: PlayerInteractEvent) = Multiblocks.context.launch { + fun onPlayerInteract(event: PlayerInteractEvent) = Multiblocks.multiblockCoroutineScope.launch { if (event.hand != EquipmentSlot.HAND) return@launch if (event.action != Action.RIGHT_CLICK_BLOCK) return@launch val player = event.player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index 64a8e3ffb3..948d80fa79 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -3,12 +3,11 @@ package net.horizonsend.ion.server.features.transport import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.power.PowerGrid +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Chunk -import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedQueue class ChunkTransportNetwork( @@ -19,39 +18,30 @@ class ChunkTransportNetwork( val extractorData = getExtractorData(chunk.inner) - val poweredMultiblockEntities = ConcurrentHashMap() - val powerGrid = PowerGrid(extractorData) + val powerGrid = PowerGrid(this) + val pipeGrid = PowerGrid(this) // TODO + val gasGrid = PowerGrid(this) // TODO init { setup() } private fun setup() { - collectPowerMultiblockEntities() + powerGrid.setup() + pipeGrid.setup() + gasGrid.setup() } fun tick() { - for ((location, extractor) in extractorData.extractorLocations) { - - } + scope.launch { powerGrid.tick() } + scope.launch { pipeGrid.tick() } + scope.launch { gasGrid.tick() } } fun save() { } - private fun tickExtractors() { - - } - - private fun collectPowerMultiblockEntities() { - chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> - if (entity !is PoweredMultiblockEntity) return@forEach - - poweredMultiblockEntities[key] = entity - } - } - private fun getExtractorData(chunk: Chunk): ExtractorData { val extractors = chunk.persistentDataContainer.get(NamespacedKeys.EXTRACTOR_DATA, ExtractorData) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt new file mode 100644 index 0000000000..b50fe44ace --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.container + +//class ItemContainer : ResourceContainer { TODO +//} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt new file mode 100644 index 0000000000..b5f3424251 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt @@ -0,0 +1,169 @@ +package net.horizonsend.ion.server.features.transport.container + +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_AMOUNT +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_CAPACITY_MAX +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_CAPACITY_MIN +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType.INTEGER +import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER +import java.util.concurrent.ConcurrentHashMap + +class NamespacedResourceContainer( + val resourceData: Map +) : ResourceContainer { + val stored: MutableMap = ConcurrentHashMap() + + fun getCapacity(resource: NamespacedKey): Int { + verifyKey(resource) + + return resourceData[resource]!!.maxAmount + } + + fun getMinimumAmount(resource: NamespacedKey): Int { + verifyKey(resource) + + return resourceData[resource]!!.minAmount + } + + override fun getContents(): Map { + return stored + } + + override fun getAmount(resource: NamespacedKey): Int { + verifyKey(resource) + + return stored.getOrPut(resource) { 0 } + } + + override fun setAmount(resource: NamespacedKey, amount: Int) { + verifyKey(resource) + + val corrected = coerce(resource, amount) + + stored[resource] = corrected + } + + /** + * Returns the amount of power that could not be added + **/ + override fun add(resource: NamespacedKey, amount: Int): Int { + verifyKey(resource) + + val current = getAmount(resource) + + val newAmount = current + amount + + setAmount(resource, newAmount) + + val maximum = getCapacity(resource) + + return if (newAmount > maximum) maximum - newAmount else 0 + } + + /** + * Returns the amount of power that could not be removed + **/ + override fun remove(resource: NamespacedKey, amount: Int): Int { + verifyKey(resource) + + val newAmount = getAmount(resource) - amount + + setAmount(resource, newAmount) + + val minimum = getMinimumAmount(resource) + + return if (newAmount < minimum) newAmount else minimum + } + + override fun canFit(resource: NamespacedKey, amount: Int): Boolean { + verifyKey(resource) + + val current = getAmount(resource) + val maximum = getCapacity(resource) + + return current + amount <= maximum + } + + override fun canRemove(resource: NamespacedKey, amount: Int): Boolean { + verifyKey(resource) + + val current = getAmount(resource) + val minimum = getMinimumAmount(resource) + + return current - amount >= minimum + } + + private fun coerce(resource: NamespacedKey, amount: Int): Int { + verifyKey(resource) + + val max = getCapacity(resource) + val min = getCapacity(resource) + + return amount.coerceIn(min..max) + } + + /** + * Verifies that the provided key is part of this container + **/ + private fun verifyKey(key: NamespacedKey) { + if (!resourceData.containsKey(key)) throw IllegalArgumentException("Container does not contain resource $key") + } + + override fun serialize(context: PersistentDataAdapterContext): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + + for ((key, data) in resourceData) { + val resourcePDC = context.newPersistentDataContainer() + + resourcePDC.set(RESOURCE_CAPACITY_MAX, INTEGER, data.maxAmount) + resourcePDC.set(RESOURCE_CAPACITY_MIN, INTEGER, data.minAmount) + resourcePDC.set(RESOURCE_AMOUNT, INTEGER, stored.getOrDefault(key, 0)) + + pdc.set(key, TAG_CONTAINER, resourcePDC) + } + + return pdc + } + + companion object { + fun deserialize(data: PersistentDataContainer): NamespacedResourceContainer { + val resourcePDCs = data.keys.associateWith { resource -> + data.get(resource, TAG_CONTAINER)!! + } + + val resourceData = resourcePDCs.mapValues { (_, pdc) -> + ResourceData( + maxAmount = pdc.get(RESOURCE_CAPACITY_MAX, INTEGER)!!, + minAmount = pdc.get(RESOURCE_CAPACITY_MIN, INTEGER)!! + ) + } + + val container = NamespacedResourceContainer(resourceData) + + resourcePDCs.entries.forEach { (resource) -> + container.setAmount(resource, resourcePDCs[resource]!!.get(RESOURCE_AMOUNT, INTEGER)!!) + } + + return container + } + } + + data class ResourceData( + val maxAmount: Int, + val minAmount: Int = 0, + ) + + class Builder { + private val resources: MutableMap = mutableMapOf() + + fun addResource(key: NamespacedKey, max: Int, min: Int = 0) : Builder { + resources[key] = ResourceData(max, min) + + return this + } + + fun build(): NamespacedResourceContainer = NamespacedResourceContainer(resources) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt new file mode 100644 index 0000000000..978d82cfb9 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt @@ -0,0 +1,28 @@ +package net.horizonsend.ion.server.features.transport.container + +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer + +/** + * A container that holds transferable resources + **/ +interface ResourceContainer { + /** + * Get transferable resources and their amounts + **/ + fun getContents(): Map + + fun getAmount(resource: T): Int + + fun setAmount(resource: T, amount: Int) + + fun canRemove(resource: T, amount: Int): Boolean + + fun canFit(resource: T, amount: Int): Boolean + + fun add(resource: T, amount: Int): Int + + fun remove(resource: T, amount: Int): Int + + fun serialize(context: PersistentDataAdapterContext): PersistentDataContainer +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt index 3cdfc20529..411b81c84a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/AbstractGrid.kt @@ -16,6 +16,11 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { val grids: Nothing = TODO("Grid system") + /** + * + **/ + open fun setup() {} + /** * **/ @@ -28,8 +33,10 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { **/ abstract fun loadNode(block: BlockSnapshot): GridNode? - // TODO maybe move this to a member function of grid node - abstract fun shouldConsolidate(node: GridNode) + /** + * + **/ + abstract fun tick() /** * Builds the grid TODO better documentation @@ -103,7 +110,7 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { * e.g. a straight section may be represented as a single node **/ private fun consolidateNodes() { - //TODO + nodes.forEach { (_, node) -> node.consolidate() } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt new file mode 100644 index 0000000000..9299269899 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt @@ -0,0 +1,19 @@ +package net.horizonsend.ion.server.features.transport.grid + +import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork +import org.bukkit.NamespacedKey + +abstract class NamespaceTransferGrid( + network: ChunkTransportNetwork, + vararg namespaces: NamespacedKey +) : AbstractGrid(network) { + val valueKeys = setOf(*namespaces) + + fun isTransferable(resourceKey: NamespacedKey): Boolean = valueKeys.contains(resourceKey) + + fun getTransferableResources(): Set = TODO() + + class ResourceContainer( + + ) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt new file mode 100644 index 0000000000..5e7a97fb2a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -0,0 +1,46 @@ +package net.horizonsend.ion.server.features.transport.grid + +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.features.transport.grid.node.JunctionNode +import net.horizonsend.ion.server.features.transport.grid.node.StraightNode +import net.horizonsend.ion.server.features.transport.grid.node.power.PowerInputNode +import org.bukkit.Material +import java.util.concurrent.ConcurrentHashMap + +class PowerGrid(network: ChunkTransportNetwork) : AbstractGrid(network) { + private val poweredMultiblockEntities = ConcurrentHashMap() + + override fun setup() { + collectPowerMultiblockEntities() + } + + override fun isNode(block: BlockSnapshot): Boolean = when (block.type) { + Material.END_ROD, Material.SPONGE, Material.IRON_BLOCK, Material.REDSTONE_BLOCK -> true + else -> false + } + + override fun loadNode(block: BlockSnapshot): GridNode? = when (block.type) { + Material.END_ROD -> StraightNode(this, block.x, block.y, block.z) + Material.SPONGE -> JunctionNode(this, block.x, block.y, block.z) + Material.IRON_BLOCK -> GrabbyNode() + Material.REDSTONE_BLOCK -> GrabbyNode() + Material.NOTE_BLOCK -> PowerExtractorNode() + Material.CRAFTING_TABLE -> PowerInputNode() + else -> null + } + + override fun tick() { + TODO("Not yet implemented") + } + + private fun collectPowerMultiblockEntities() { + network.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> + if (entity !is PoweredMultiblockEntity) return@forEach + + poweredMultiblockEntities[key] = entity + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt index 1e8c4409be..e188623e06 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt @@ -1,5 +1,17 @@ package net.horizonsend.ion.server.features.transport.grid.node -abstract class JunctionNode : GridNode { +import net.horizonsend.ion.server.features.transport.grid.AbstractGrid +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap +class JunctionNode( + override val parent: AbstractGrid, + override val x: Int, + override val y: Int, + override val z: Int, + override val neighbors: ConcurrentHashMap = ConcurrentHashMap() +) : GridNode { + override fun consolidate() { + return + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt new file mode 100644 index 0000000000..839ca6b28a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.grid.node + +enum class NodeType { + ORIGIN, + INTERMEDIATE, + DESTINATION +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt index fec169fcd3..f2cbedc74d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt @@ -16,7 +16,7 @@ class StraightNode( override val y: Int, override val z: Int, override val neighbors: ConcurrentHashMap = ConcurrentHashMap(), - val positions: Set + val positions: Set = setOf() ) : GridNode { override fun consolidate() { // Check neighbors in straight line diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt new file mode 100644 index 0000000000..3553af485e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.grid.node.power + +class GrabbyNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt new file mode 100644 index 0000000000..8d7b65d17a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.grid.node.power + +class PowerExtractorNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerInputNode.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerInputNode.kt index 613cb517e3..f28a37cf07 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerInputNode.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.grid.power +package net.horizonsend.ion.server.features.transport.grid.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.grid.node.GridNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt new file mode 100644 index 0000000000..840834e7fb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt @@ -0,0 +1,3 @@ +package net.horizonsend.ion.server.features.transport.grid.node.power + +interface PowerNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt deleted file mode 100644 index 1581ceb11c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.power - -import net.horizonsend.ion.server.features.transport.ExtractorData - -class PowerGrid(private val extractorData: ExtractorData) { - -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt deleted file mode 100644 index e0c80884dc..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerNodes.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.power - -import net.horizonsend.ion.server.features.transport.grid.node.GridNode -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -abstract class PowerNode( - override val x: Int, - override val y: Int, - override val z: Int, - override val neighbors: ConcurrentHashMap = ConcurrentHashMap() -) : GridNode { - -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 862fb4f56b..6cd356ece5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -83,6 +83,10 @@ object NamespacedKeys { val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") val EXTRACTOR_DATA = key("extractor_data") + val RESOURCE_CAPACITY_MAX = key("resource_capacity_max") + val RESOURCE_CAPACITY_MIN = key("resource_capacity_min") + val RESOURCE_AMOUNT = key("resource_amount") + val PROCESSING_PROGRESS = key("processing_progress") fun key(key: String) = NamespacedKey(IonServer, key) From 4bb067579f62d6cadfe772530959a7af80588a4d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 23 Mar 2024 02:23:59 -0500 Subject: [PATCH 018/500] more work --- .../multiblock/entity/MultiblockEntity.kt | 10 ++- .../multiblock/type/misc/TestMultiblock.kt | 4 +- .../features/multiblock/util/BlockSnapshot.kt | 4 + .../transport/ChunkTransportNetwork.kt | 2 +- .../grid/{AbstractGrid.kt => Grid.kt} | 30 +++---- .../transport/grid/NamespaceTransferGrid.kt | 2 +- .../features/transport/grid/PowerGrid.kt | 46 ----------- .../transport/grid/node/Consolidatable.kt | 11 +++ .../features/transport/grid/node/GridNode.kt | 27 +++++-- .../transport/grid/node/JunctionNode.kt | 13 ++- .../transport/grid/node/LinearNode.kt | 45 +++++++++++ .../transport/grid/node/StraightNode.kt | 62 --------------- .../transport/grid/node/power/GrabbyNode.kt | 4 - .../grid/node/power/PowerExtractorNode.kt | 4 - .../transport/grid/node/power/PowerNodes.kt | 3 - .../transport/grid/power/PowerGrid.kt | 79 +++++++++++++++++++ .../transport/grid/power/node/GrabbyNode.kt | 4 + .../grid/power/node/PowerExtractorNode.kt | 39 +++++++++ .../power => power/node}/PowerInputNode.kt | 2 +- .../transport/grid/power/node/PowerNodes.kt | 3 + .../ion/server/miscellaneous/utils/Blocks.kt | 16 +++- .../server/miscellaneous/utils/Collections.kt | 14 ++++ 22 files changed, 264 insertions(+), 160 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{AbstractGrid.kt => Grid.kt} (81%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{node/power => power/node}/PowerInputNode.kt (94%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 08ece4222d..e858397827 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -19,6 +19,8 @@ import org.bukkit.block.Sign * @param world The world this multiblock is in * * @param type The type of multiblock this entity represents + * + * @param signDirection The direction to find the sign from the origin block (the block the sign is placed on) **/ abstract class MultiblockEntity( val type: Multiblock, @@ -27,7 +29,7 @@ abstract class MultiblockEntity( var y: Int, var z: Int, var world: World, - var signOffset: BlockFace + var signDirection: BlockFace ) { /** * Returns the origin of this multiblock as a Location @@ -54,7 +56,7 @@ abstract class MultiblockEntity( * This data is serialized and stored on the chunk when not loaded. **/ fun store(): PersistentMultiblockData { - val store = PersistentMultiblockData(x, y, z, type, signOffset) + val store = PersistentMultiblockData(x, y, z, type, signDirection) storeAdditionalData(store) return store @@ -64,7 +66,7 @@ abstract class MultiblockEntity( * Gets the sign of this multiblock **/ suspend fun getSign(): Sign? { - val signLoc = Vec3i(x, y, z) + Vec3i(signOffset.modX, 0, signOffset.modZ) + val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) return getBukkitBlockState(world.getBlockAt(signLoc.x, signLoc.y, signLoc.z), loadChunks = false) as? Sign } @@ -79,7 +81,7 @@ abstract class MultiblockEntity( * **/ fun getBlockRelative(backFourth: Int, leftRight: Int, upDown: Int): Block { - val (x, y, z) = getRelative(vec3i, signOffset.oppositeFace, backFourth, leftRight, upDown) + val (x, y, z) = getRelative(vec3i, signDirection.oppositeFace, backFourth, leftRight, upDown) return world.getBlockAt(x, y, z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 5719e5b7ce..cb9df18e7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -70,7 +70,7 @@ object TestMultiblock : Multiblock(), EntityMultiblock = ConcurrentHashMap() + val world get() = network.chunk.world val grids: Nothing = TODO("Grid system") @@ -33,6 +34,8 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { **/ abstract fun loadNode(block: BlockSnapshot): GridNode? + abstract fun processBlockChange(previous: BlockSnapshot, new: BlockSnapshot) + /** * **/ @@ -43,6 +46,7 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { **/ fun build() = network.scope.launch { collectAllNodes().join() + collectNeighbors() consolidateNodes() buildGraph() } @@ -83,7 +87,6 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { val node = loadNode(snapshot) ?: continue nodes[toBlockKey(realX, realY, realZ)] = node - collectNeighbors(node) } } } @@ -92,16 +95,8 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { /** * Get the neighbors of a node **/ - private fun collectNeighbors(node: GridNode) { - for (direction in ADJACENT_BLOCK_FACES) { - val newX = node.x + direction.modX - val newY = node.y + direction.modY - val newZ = node.z + direction.modZ - - val possibleNode = nodes[toBlockKey(newX, newY, newZ)] ?: continue - - node.neighbors[direction] = possibleNode - } + private fun collectNeighbors() { + nodes.values.forEach { node -> node.collectNeighbors() } } /** @@ -110,7 +105,9 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { * e.g. a straight section may be represented as a single node **/ private fun consolidateNodes() { - nodes.forEach { (_, node) -> node.consolidate() } + nodes.forEach { (_, node) -> + if (node is Consolidatable) node.consolidate() + } } /** @@ -119,4 +116,9 @@ abstract class AbstractGrid(val network: ChunkTransportNetwork) { private fun buildGraph() { //TODO } + + fun getNode(x: Int, y: Int, z: Int): GridNode? { + val key = toBlockKey(x, y, z) + return nodes[key] + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt index 9299269899..0368d41ea7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt @@ -6,7 +6,7 @@ import org.bukkit.NamespacedKey abstract class NamespaceTransferGrid( network: ChunkTransportNetwork, vararg namespaces: NamespacedKey -) : AbstractGrid(network) { +) : Grid(network) { val valueKeys = setOf(*namespaces) fun isTransferable(resourceKey: NamespacedKey): Boolean = valueKeys.contains(resourceKey) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt deleted file mode 100644 index 5e7a97fb2a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ /dev/null @@ -1,46 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.grid.node.GridNode -import net.horizonsend.ion.server.features.transport.grid.node.JunctionNode -import net.horizonsend.ion.server.features.transport.grid.node.StraightNode -import net.horizonsend.ion.server.features.transport.grid.node.power.PowerInputNode -import org.bukkit.Material -import java.util.concurrent.ConcurrentHashMap - -class PowerGrid(network: ChunkTransportNetwork) : AbstractGrid(network) { - private val poweredMultiblockEntities = ConcurrentHashMap() - - override fun setup() { - collectPowerMultiblockEntities() - } - - override fun isNode(block: BlockSnapshot): Boolean = when (block.type) { - Material.END_ROD, Material.SPONGE, Material.IRON_BLOCK, Material.REDSTONE_BLOCK -> true - else -> false - } - - override fun loadNode(block: BlockSnapshot): GridNode? = when (block.type) { - Material.END_ROD -> StraightNode(this, block.x, block.y, block.z) - Material.SPONGE -> JunctionNode(this, block.x, block.y, block.z) - Material.IRON_BLOCK -> GrabbyNode() - Material.REDSTONE_BLOCK -> GrabbyNode() - Material.NOTE_BLOCK -> PowerExtractorNode() - Material.CRAFTING_TABLE -> PowerInputNode() - else -> null - } - - override fun tick() { - TODO("Not yet implemented") - } - - private fun collectPowerMultiblockEntities() { - network.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> - if (entity !is PoweredMultiblockEntity) return@forEach - - poweredMultiblockEntities[key] = entity - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt new file mode 100644 index 0000000000..74735eaf13 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.transport.grid.node + +/** + * A node that may be consolidated. + **/ +interface Consolidatable { + /** + * Consolidates this node if possible + **/ + fun consolidate() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt index 1e07e240b7..7f5fef41e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt @@ -1,12 +1,13 @@ package net.horizonsend.ion.server.features.transport.grid.node -import net.horizonsend.ion.server.features.transport.grid.AbstractGrid +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap interface GridNode { - val parent: AbstractGrid + val parentGrid: Grid val x: Int val y: Int val z: Int @@ -15,15 +16,25 @@ interface GridNode { val neighbors: ConcurrentHashMap + /** + * Collects the neighbors of this node + **/ + fun collectNeighbors() { + for (direction in ADJACENT_BLOCK_FACES) { + val newX = x + direction.modX + val newY = y + direction.modY + val newZ = z + direction.modZ + + val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue + + neighbors[direction] = possibleNode + } + } + fun getNeighbor(face: BlockFace): GridNode? { return neighbors[face] } - /** - * Consolidates this node if possible - **/ - fun consolidate() - /** * Replace this node with another and update its neighbors **/ @@ -33,5 +44,7 @@ interface GridNode { neighbor.neighbors[neighborRelation] = neighbor } + + parentGrid.nodes[key] = new } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt index e188623e06..c320a03597 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt @@ -1,17 +1,16 @@ package net.horizonsend.ion.server.features.transport.grid.node -import net.horizonsend.ion.server.features.transport.grid.AbstractGrid +import net.horizonsend.ion.server.features.transport.grid.Grid import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap +/** + * An omnidirectional node + **/ class JunctionNode( - override val parent: AbstractGrid, + override val parentGrid: Grid, override val x: Int, override val y: Int, override val z: Int, override val neighbors: ConcurrentHashMap = ConcurrentHashMap() -) : GridNode { - override fun consolidate() { - return - } -} +) : GridNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt new file mode 100644 index 0000000000..c599335beb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt @@ -0,0 +1,45 @@ +package net.horizonsend.ion.server.features.transport.grid.node + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.faces +import net.horizonsend.ion.server.miscellaneous.utils.iterator +import org.bukkit.Axis +import org.bukkit.block.BlockFace +import org.bukkit.block.data.Directional +import java.util.concurrent.ConcurrentHashMap + +class LinearNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, + val axis: Axis, + val occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) +) : GridNode, Consolidatable { + constructor( + grid: Grid, + x: Int, + y: Int, + z: Int, + data: Directional, + occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) + ) : this(grid, x, y, z, data.facing.axis, occupiedPositions) + + override val neighbors: ConcurrentHashMap = ConcurrentHashMap() + + override fun consolidate() { + for (face in this.axis.faces) { + val node = getNeighbor(face) ?: continue + if (node !is LinearNode) continue + + // Eat the neighbor + occupiedPositions.addAll(node.occupiedPositions) + + // Replace the neighbor with this + node.replace(this) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt deleted file mode 100644 index f2cbedc74d..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/StraightNode.kt +++ /dev/null @@ -1,62 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node - -import net.horizonsend.ion.server.features.transport.grid.AbstractGrid -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_PAIRS -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -/** - * Represents a straight connection, e.g. wire, glass pane - * - * @param positions The keys of the positions that this straight node occupies - **/ -class StraightNode( - override val parent: AbstractGrid, - override val x: Int, - override val y: Int, - override val z: Int, - override val neighbors: ConcurrentHashMap = ConcurrentHashMap(), - val positions: Set = setOf() -) : GridNode { - override fun consolidate() { - // Check neighbors in straight line - for (adjacentPairs in ADJACENT_PAIRS) { - if (!adjacentPairs.all { - getNeighbor(it) is StraightNode - }) continue - - val neighborNodes = adjacentPairs.mapNotNull(::getNeighbor) - - // Keys of all 3 - val occupiedKeys = neighborNodes.mapTo(mutableSetOf()) { it.key }.plus(key) - - // Add all the merged neighbors together - val newNeighborsList = ConcurrentHashMap() - neighborNodes.mapTo(mutableListOf()) { it.neighbors }.plus(neighbors).forEach(newNeighborsList::putAll) - - // Create a new node representing a single straight connection between all - val new = StraightNode( - parent, - x, y, z, - newNeighborsList, - occupiedKeys - ) - - // Replace the neighbor positions with the new straight one and update neighbor relations - neighborNodes.forEach { node -> - val key = node.key - - parent.nodes[key] = new - - node.replace(new) - } - - // Replace this one - parent.nodes[key] = new - replace(new) - - // Only merge once - return - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt deleted file mode 100644 index 3553af485e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/GrabbyNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node.power - -class GrabbyNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt deleted file mode 100644 index 8d7b65d17a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerExtractorNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node.power - -class PowerExtractorNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt deleted file mode 100644 index 840834e7fb..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerNodes.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node.power - -interface PowerNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt new file mode 100644 index 0000000000..566c4538db --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt @@ -0,0 +1,79 @@ +package net.horizonsend.ion.server.features.transport.grid.power + +import net.horizonsend.ion.server.features.customblocks.CustomBlocks +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.features.transport.grid.node.JunctionNode +import net.horizonsend.ion.server.features.transport.grid.node.LinearNode +import net.horizonsend.ion.server.features.transport.grid.power.node.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.grid.power.node.PowerInputNode +import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp +import org.bukkit.Material +import org.bukkit.block.data.Directional +import java.util.concurrent.ConcurrentHashMap + +class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { + private val poweredMultiblockEntities = ConcurrentHashMap() + + override fun setup() { + collectPowerMultiblockEntities() + } + + override fun isNode(block: BlockSnapshot): Boolean = when (block.type) { + Material.END_ROD, Material.SPONGE, Material.IRON_BLOCK, Material.REDSTONE_BLOCK -> true + else -> false + } + + override fun loadNode(block: BlockSnapshot): GridNode? { + val x = block.x + val y = block.y + val z = block.z + + return when { + // Extract power from storage + block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z) + + // Add power to storage + block.type == Material.NOTE_BLOCK -> PowerInputNode() + + // Straight wires + block.type == Material.END_ROD -> LinearNode(this, x, y, z, block.data as Directional) + + // Omnidirectional wires + block.type == Material.SPONGE -> JunctionNode(this, x, y, z) + + // Merge node behavior + block.type == Material.IRON_BLOCK -> MergeNode() + block.type == Material.REDSTONE_BLOCK -> MergeNode() + + // Split power evenly + block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode() + + // Redstone controlled gate + block.type.isRedstoneLamp -> GateNode() + + // Power flow meter + block.type == Material.OBSERVER -> PowerFlowMeter() + else -> null + } + } + + override fun processBlockChange(previous: BlockSnapshot, new: BlockSnapshot) { + + } + + override fun tick() { + TODO("Not yet implemented") + } + + private fun collectPowerMultiblockEntities() { + network.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> + if (entity !is PoweredMultiblockEntity) return@forEach + + poweredMultiblockEntities[key] = entity + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt new file mode 100644 index 0000000000..c1309a80ff --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.grid.power.node + +class GrabbyNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt new file mode 100644 index 0000000000..f6a58d8e4e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt @@ -0,0 +1,39 @@ +package net.horizonsend.ion.server.features.transport.grid.power.node + +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import org.bukkit.World +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class PowerExtractorNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, + override val neighbors: ConcurrentHashMap = ConcurrentHashMap(), + val solarPanel: Boolean = false +) : GridNode { + var lastTicked: Long = System.currentTimeMillis() + + fun tickSolarPanel() { + val time = System.currentTimeMillis() + val deltaMs = time - lastTicked + lastTicked = time + + val deltaSeconds = deltaMs / 1000.0 + val power = getPower(deltaSeconds) + } + + private fun getPower(delta: Double): Int { + val environment = parentGrid.world.environment + + val power = 5.0 / if (environment == World.Environment.NORMAL) 1.0 else 2.0 + + return (power * delta).toInt() + } + + companion object { + fun isSolarPanel(parentGrid: Grid, x: Int, y: Int, z: Int): Boolean = TODO() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerInputNode.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerInputNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerInputNode.kt index f28a37cf07..dfa7b31f00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerInputNode.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.grid.node.power +package net.horizonsend.ion.server.features.transport.grid.power.node import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.grid.node.GridNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt new file mode 100644 index 0000000000..c00bbc8bbc --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt @@ -0,0 +1,3 @@ +package net.horizonsend.ion.server.features.transport.grid.power.node + +interface PowerNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index d98365c5d3..7deeff97f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -80,10 +80,10 @@ val ADJACENT_BLOCK_FACES: Set = ImmutableSet.of( BlockFace.DOWN ) -val ADJACENT_PAIRS: Set> = ImmutableSet.of( - ImmutableSet.of(BlockFace.NORTH, BlockFace.SOUTH), - ImmutableSet.of(BlockFace.EAST, BlockFace.WEST), - ImmutableSet.of(BlockFace.NORTH, BlockFace.SOUTH) +val ADJACENT_PAIRS: Map> = mapOf( + Axis.Z to ImmutableSet.of(BlockFace.NORTH, BlockFace.SOUTH), + Axis.X to ImmutableSet.of(BlockFace.EAST, BlockFace.WEST), + Axis.Y to ImmutableSet.of(BlockFace.UP, BlockFace.DOWN) ) val CARDINAL_BLOCK_FACES: Set = ImmutableSet.of( @@ -119,6 +119,14 @@ val BlockFace.axis: Axis else -> error("Unsupported axis for BlockFace: $this") } +val Axis.faces: Pair + get() = when (this) { + Axis.Z -> BlockFace.NORTH to BlockFace.SOUTH + Axis.X -> BlockFace.EAST to BlockFace.WEST + Axis.Y -> BlockFace.UP to BlockFace.DOWN + else -> error("Unsupported axis for BlockFace: $this") + } + fun BlockFace.matchesAxis(other: BlockFace) = this.axis == other.axis fun Sign.getFacing(): BlockFace = diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index 3947972faa..1df66ae84f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -103,3 +103,17 @@ fun Iterable.weightedRandomOrNull(random: Random = ThreadLocalRandom.curr } fun Iterable.weightedRandom(random: Random = ThreadLocalRandom.current().asKotlinRandom(), selector: (T) -> Double): T = weightedRandomOrNull(random, selector) ?: throw NoSuchElementException() + +// Idk why I did this +operator fun Pair.iterator(): Iterator = object : Iterator { + var current: Boolean = false + + override fun hasNext(): Boolean { + return !current + } + + override fun next(): A { + current = true + return second + } +} From 5564290b85f0896e102cb43de7a5a07994b87687 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Mar 2024 03:13:58 -0500 Subject: [PATCH 019/500] slight node rework, implement more, organization --- .../transport/ChunkTransportNetwork.kt | 2 +- .../container/NamespacedResourceContainer.kt | 4 + .../server/features/transport/grid/Grid.kt | 4 +- .../transport/grid/{power => }/PowerGrid.kt | 19 +++-- .../transport/grid/node/ExtractorNode.kt | 13 ---- .../features/transport/grid/node/GridNode.kt | 50 ------------ .../transport/grid/node/JunctionNode.kt | 16 ---- .../features/transport/grid/node/NodeType.kt | 7 -- .../transport/grid/power/node/GrabbyNode.kt | 4 - .../grid/power/node/PowerExtractorNode.kt | 39 ---------- .../transport/grid/power/node/PowerNodes.kt | 3 - .../{grid => }/node/Consolidatable.kt | 2 +- .../features/transport/node/ExtractorNode.kt | 16 ++++ .../features/transport/node/GridNode.kt | 77 +++++++++++++++++++ .../features/transport/node/NodeType.kt | 7 ++ .../transport/node/general/JunctionNode.kt | 22 ++++++ .../{grid/node => node/general}/LinearNode.kt | 11 ++- .../transport/node/power/GrabbyNode.kt | 4 + .../node/power/PowerExtractorNode.kt | 60 +++++++++++++++ .../node => node/power}/PowerInputNode.kt | 24 ++++-- .../transport/node/power/PowerNodes.kt | 10 +++ .../persistence/NamespacedKeys.kt | 2 +- .../server/miscellaneous/utils/Collections.kt | 11 +++ 23 files changed, 252 insertions(+), 155 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{power => }/PowerGrid.kt (78%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{grid => }/node/Consolidatable.kt (69%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{grid/node => node/general}/LinearNode.kt (73%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{grid/power/node => node/power}/PowerInputNode.kt (61%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index c6edc78949..948d80fa79 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import net.horizonsend.ion.server.features.transport.grid.power.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Chunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt index b5f3424251..8527fbb1ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.container +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_AMOUNT import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_CAPACITY_MAX import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_CAPACITY_MIN @@ -148,6 +149,9 @@ class NamespacedResourceContainer( return container } + + fun powerContainer(maxPower: Int): NamespacedResourceContainer = + NamespacedResourceContainer(mapOf(NamespacedKeys.POWER to ResourceData(minAmount = 0, maxAmount = maxPower))) } data class ResourceData( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt index 62542a4e49..d1d5fa6d98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt @@ -6,8 +6,8 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.grid.node.Consolidatable -import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.features.transport.node.Consolidatable +import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import java.util.concurrent.ConcurrentHashMap diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt similarity index 78% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt index 566c4538db..07db3129d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -1,15 +1,14 @@ -package net.horizonsend.ion.server.features.transport.grid.power +package net.horizonsend.ion.server.features.transport.grid import net.horizonsend.ion.server.features.customblocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.grid.Grid -import net.horizonsend.ion.server.features.transport.grid.node.GridNode -import net.horizonsend.ion.server.features.transport.grid.node.JunctionNode -import net.horizonsend.ion.server.features.transport.grid.node.LinearNode -import net.horizonsend.ion.server.features.transport.grid.power.node.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.grid.power.node.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.node.general.JunctionNode +import net.horizonsend.ion.server.features.transport.node.general.LinearNode +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp import org.bukkit.Material import org.bukkit.block.data.Directional @@ -37,7 +36,7 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z) // Add power to storage - block.type == Material.NOTE_BLOCK -> PowerInputNode() + block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) // Straight wires block.type == Material.END_ROD -> LinearNode(this, x, y, z, block.data as Directional) @@ -65,6 +64,10 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { } + fun removeNode(key: Long) { + + } + override fun tick() { TODO("Not yet implemented") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt deleted file mode 100644 index c0cb8503e0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/ExtractorNode.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node - -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -abstract class ExtractorNode( - override val x: Int, - override val y: Int, - override val z: Int, - override val neighbors: ConcurrentHashMap = ConcurrentHashMap() -) : GridNode { - -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt deleted file mode 100644 index 7f5fef41e9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/GridNode.kt +++ /dev/null @@ -1,50 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node - -import net.horizonsend.ion.server.features.transport.grid.Grid -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -interface GridNode { - val parentGrid: Grid - val x: Int - val y: Int - val z: Int - - val key get() = toBlockKey(x, y, z) - - val neighbors: ConcurrentHashMap - - /** - * Collects the neighbors of this node - **/ - fun collectNeighbors() { - for (direction in ADJACENT_BLOCK_FACES) { - val newX = x + direction.modX - val newY = y + direction.modY - val newZ = z + direction.modZ - - val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue - - neighbors[direction] = possibleNode - } - } - - fun getNeighbor(face: BlockFace): GridNode? { - return neighbors[face] - } - - /** - * Replace this node with another and update its neighbors - **/ - fun replace(new: GridNode) { - for ((offset, neighbor) in neighbors) { - val neighborRelation = offset.oppositeFace - - neighbor.neighbors[neighborRelation] = neighbor - } - - parentGrid.nodes[key] = new - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt deleted file mode 100644 index c320a03597..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/JunctionNode.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node - -import net.horizonsend.ion.server.features.transport.grid.Grid -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -/** - * An omnidirectional node - **/ -class JunctionNode( - override val parentGrid: Grid, - override val x: Int, - override val y: Int, - override val z: Int, - override val neighbors: ConcurrentHashMap = ConcurrentHashMap() -) : GridNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt deleted file mode 100644 index 839ca6b28a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/NodeType.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.node - -enum class NodeType { - ORIGIN, - INTERMEDIATE, - DESTINATION -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt deleted file mode 100644 index c1309a80ff..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/GrabbyNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.power.node - -class GrabbyNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt deleted file mode 100644 index f6a58d8e4e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerExtractorNode.kt +++ /dev/null @@ -1,39 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.power.node - -import net.horizonsend.ion.server.features.transport.grid.Grid -import net.horizonsend.ion.server.features.transport.grid.node.GridNode -import org.bukkit.World -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -class PowerExtractorNode( - override val parentGrid: Grid, - override val x: Int, - override val y: Int, - override val z: Int, - override val neighbors: ConcurrentHashMap = ConcurrentHashMap(), - val solarPanel: Boolean = false -) : GridNode { - var lastTicked: Long = System.currentTimeMillis() - - fun tickSolarPanel() { - val time = System.currentTimeMillis() - val deltaMs = time - lastTicked - lastTicked = time - - val deltaSeconds = deltaMs / 1000.0 - val power = getPower(deltaSeconds) - } - - private fun getPower(delta: Double): Int { - val environment = parentGrid.world.environment - - val power = 5.0 / if (environment == World.Environment.NORMAL) 1.0 else 2.0 - - return (power * delta).toInt() - } - - companion object { - fun isSolarPanel(parentGrid: Grid, x: Int, y: Int, z: Int): Boolean = TODO() - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt deleted file mode 100644 index c00bbc8bbc..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerNodes.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.power.node - -interface PowerNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt index 74735eaf13..f4ba54c9be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/Consolidatable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.grid.node +package net.horizonsend.ion.server.features.transport.node /** * A node that may be consolidated. diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt new file mode 100644 index 0000000000..c42b3e58bb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt @@ -0,0 +1,16 @@ +package net.horizonsend.ion.server.features.transport.node + +import net.horizonsend.ion.server.features.transport.container.ResourceContainer +import net.horizonsend.ion.server.features.transport.grid.Grid +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +abstract class ExtractorNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() +) : GridNode { + abstract fun getExtractableInventories(): Collection> +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt new file mode 100644 index 0000000000..d56f2a9f8a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt @@ -0,0 +1,77 @@ +package net.horizonsend.ion.server.features.transport.node + +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.setOrRemove +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +interface GridNode { + val parentGrid: Grid + val x: Int + val y: Int + val z: Int + + val key get() = toBlockKey(x, y, z) + + val transferableNeighbors: ConcurrentHashMap + + /** + * Collects the neighbors of this node + **/ + fun collectNeighbors() { + // In every adjacent direction + for (direction in ADJACENT_BLOCK_FACES) { + val newX = x + direction.modX + val newY = y + direction.modY + val newZ = z + direction.modZ + + // All nodes should already be collected + val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue + + // Only add transferable nodes + if (!isTransferableTo(direction, possibleNode)) continue + + transferableNeighbors[direction] = possibleNode + } + } + + /** + * Notifies this node of a changed neighbor + * + * Will handle adding it to the transferable list, if able + **/ + fun neighborChanged(offset: BlockFace, replacement: GridNode?) { + if (replacement != null) { + if (!isTransferableTo(offset, replacement)) return + + transferableNeighbors[offset] = replacement + } else { + transferableNeighbors.remove(offset) + } + } + + /** + * Whether a power transfer may take place between these two nodes + **/ + fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean + + /** + * Returns a possible neighbor of this node + **/ + fun getNeighbor(face: BlockFace): GridNode? { + return transferableNeighbors[face] + } + + /** + * Replace this node with another and update its neighbors + **/ + fun replace(new: GridNode?) { + for ((offset, neighbor) in transferableNeighbors) { + neighbor.neighborChanged(offset.oppositeFace, new) + + parentGrid.nodes.setOrRemove(key, new) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt new file mode 100644 index 0000000000..f5cea12347 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.node + +enum class NodeType { + ORIGIN, + INTERMEDIATE, + DESTINATION +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt new file mode 100644 index 0000000000..3394cca28c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -0,0 +1,22 @@ +package net.horizonsend.ion.server.features.transport.node.general + +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.ExtractorNode +import net.horizonsend.ion.server.features.transport.node.GridNode +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +/** + * An omnidirectional node + **/ +class JunctionNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() +) : GridNode { + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + return node !is ExtractorNode + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt similarity index 73% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index c599335beb..b869794005 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/node/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -1,7 +1,9 @@ -package net.horizonsend.ion.server.features.transport.grid.node +package net.horizonsend.ion.server.features.transport.node.general import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.Consolidatable +import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.faces @@ -28,7 +30,12 @@ class LinearNode( occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) ) : this(grid, x, y, z, data.facing.axis, occupiedPositions) - override val neighbors: ConcurrentHashMap = ConcurrentHashMap() + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + // Only allow transfer to wires along the same axis + return offset.axis == axis + } override fun consolidate() { for (face in this.axis.faces) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt new file mode 100644 index 0000000000..80e0fb782e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.power + +class GrabbyNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt new file mode 100644 index 0000000000..0ddaa00a93 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -0,0 +1,60 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import kotlinx.coroutines.runBlocking +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.ExtractorNode +import net.horizonsend.ion.server.features.transport.node.GridNode +import org.bukkit.Material +import org.bukkit.NamespacedKey +import org.bukkit.World +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class PowerExtractorNode( + parentGrid: Grid, + x: Int, + y: Int, + z: Int, + transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap(), + val solarPanel: Boolean = isSolarPanel(parentGrid, x, y, z) +) : ExtractorNode(parentGrid, x, y, z, transferableNeighbors) { + var lastTicked: Long = System.currentTimeMillis() + + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + // Don't send power to other extractors + if (node is PowerExtractorNode) return false + + // Power may only exit from an input + if (node is PowerInputNode) return false + + // All others allowed + return true + } + + fun tickSolarPanel(): Int { + val time = System.currentTimeMillis() + val deltaMs = time - lastTicked + lastTicked = time + + val deltaSeconds = deltaMs / 1000.0 + return getPower(deltaSeconds) + } + + private fun getPower(delta: Double): Int { + val environment = parentGrid.world.environment + + val power = 5.0 / if (environment == World.Environment.NORMAL) 1.0 else 2.0 + + return (power * delta).toInt() + } + + companion object { + fun isSolarPanel(parentGrid: Grid, x: Int, y: Int, z: Int): Boolean = runBlocking { + val aboveOne = getBlockSnapshotAsync(parentGrid.world, x, y + 1, z, false) + val aboveTwo = getBlockSnapshotAsync(parentGrid.world, x, y + 2, z, false) + + return@runBlocking aboveOne?.type == Material.DIAMOND_BLOCK && aboveTwo?.type == Material.DAYLIGHT_DETECTOR + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt similarity index 61% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerInputNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index dfa7b31f00..1cceb7c0f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/power/node/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,22 +1,30 @@ -package net.horizonsend.ion.server.features.transport.grid.power.node +package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.node.GridNode +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -abstract class PowerInputNode( - x: Int, - y: Int, - z: Int, - neighbors: ConcurrentHashMap = ConcurrentHashMap() -) : PowerNode(x, y, z, neighbors) { +class PowerInputNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap(), + override val multiblocks: Collection +) : GridNode, PowerNode { /** * Gets the multiblocks to which this can input power **/ suspend fun getMultiblocks(): Collection = TODO() + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + // May only accept power + return false + } + companion object { /** * The offsets at which a multiblock sign might be found. diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt new file mode 100644 index 0000000000..00bba1da7b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity + +/** + * + **/ +interface PowerNode { + val multiblocks: Collection +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 6cd356ece5..bdf8c3b295 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -56,7 +56,7 @@ object NamespacedKeys { @Deprecated("") val ORE_CHECK = key("oreCheck") - @Deprecated("") val POWER = key("power") + val POWER = key("power") val TUBE_BUTTONS = key("tube_buttons") val MATERIAL = key("material") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index 1df66ae84f..f77bee0c6f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -117,3 +117,14 @@ operator fun Pair.iterator(): Iterator = object : Iterator { return second } } + +/** + * Set a value in a map, or remove it if provided null + **/ +fun MutableMap.setOrRemove(key: K, value: V?) { + if (value == null) { + remove(key) + } else { + set(key, value) + } +} From 9a30c1ea732ae3c36de75bb2bb04912f81a7b65c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 30 Mar 2024 01:50:36 -0500 Subject: [PATCH 020/500] compilable --- server/build.gradle.kts | 1 - .../server/command/admin/IonChunkCommand.kt | 20 +++++++ .../multiblock/ChunkMultiblockManager.kt | 14 ++++- .../entity/type/PoweredMultiblockEntity.kt | 8 +-- .../features/multiblock/util/BlockSnapshot.kt | 15 ++++- .../transport/ChunkTransportNetwork.kt | 19 ++++++ .../server/features/transport/grid/Grid.kt | 11 +--- .../features/transport/grid/PowerGrid.kt | 53 ++++++++++++----- .../features/transport/node/ExtractorNode.kt | 3 +- .../features/transport/node/GridNode.kt | 23 ++++++++ .../transport/node/general/GateNode.kt | 24 ++++++++ .../transport/node/general/JunctionNode.kt | 27 ++++++++- .../transport/node/general/LinearNode.kt | 5 ++ .../transport/node/power/MergeNode.kt | 25 ++++++++ .../node/power/PowerExtractorNode.kt | 30 ++++++++-- .../transport/node/power/PowerFlowMeter.kt | 29 ++++++++++ .../transport/node/power/PowerInputNode.kt | 36 ++++++++++-- .../transport/node/power/PowerNodes.kt | 2 +- .../transport/node/power/SplitterNode.kt | 24 ++++++++ .../features/transport/step/PowerStep.kt | 13 +++++ .../server/features/transport/step/Step.kt | 58 +++++++++++++++++++ .../features/transport/step/TransferStatus.kt | 8 +++ .../ion/server/features/world/IonChunk.kt | 13 +++++ 23 files changed, 416 insertions(+), 45 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 32ba0aa093..4714110462 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -45,7 +45,6 @@ dependencies { compileOnly("xyz.xenondevs.invui:invui:1.43") // Downloaded via paper library manager for remapping // Included Dependencies - implementation("com.google.guava:guava:33.1.0-jre") implementation("com.manya:persistent-data-types:1.0.25") implementation("co.aikar:acf-paper:0.5.1-SNAPSHOT") implementation("com.daveanthonythomas.moshipack:moshipack:1.0.1") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 47e52d72ab..1c2833ca2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.command.admin import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.utils.text.formatPaginatedMenu @@ -49,4 +50,23 @@ object IonChunkCommand : SLCommand() { ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) } } + + @Subcommand("dump nodes") + @CommandCompletion("power|item|gas") + fun dumpNodes(sender: Player, network: String) { + val ionChunk = sender.chunk.ion() + + val grid = when (network) { + "power" -> ionChunk.transportNetwork.powerGrid + "item" -> ionChunk.transportNetwork.pipeGrid + "gas" -> ionChunk.transportNetwork.gasGrid + else -> fail { "invalid network" } + } + + grid.nodes.forEach { (t, u) -> + val vec = toVec3i(u.key) + + sender.highlightBlock(vec, 50L) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 616d86ca93..86a0c3da79 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LIST import org.slf4j.LoggerFactory import java.util.concurrent.ConcurrentHashMap @@ -116,7 +117,18 @@ class ChunkMultiblockManager(val chunk: IonChunk) { * Load the multiblocks from the persistent data container upon chunk load. **/ private fun loadMultiblocks() { - val serialized = chunk.inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, LIST.dataContainers()) ?: return + val serialized = try { + chunk.inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, LIST.dataContainers()) ?: return + } catch (e: IllegalArgumentException) { + log.warn("Could not load chunks multiblocks for $chunk") + if (e.message == "The found tag instance (NBTTagList) cannot store List") { + log.info("Found outdated list tag, removing") + + chunk.inner.persistentDataContainer.remove(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES) + } + + listOf() + } for (serializedMultiblockData in serialized) { val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, chunk.inner.persistentDataContainer.adapterContext) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index c13e1b8ff6..cbf563612e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -9,7 +9,7 @@ import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { - var power: Int + var powerUnsafe: Int val type: PowerStoringMultiblock val maxPower get() = type.maxPower @@ -17,11 +17,11 @@ interface PoweredMultiblockEntity { fun setPower(amount: Int) { val correctedPower = amount.coerceIn(0, maxPower) - power = correctedPower + powerUnsafe = correctedPower } fun getPower(): Int { - return power + return powerUnsafe } /** @@ -66,6 +66,6 @@ interface PoweredMultiblockEntity { /** Store power data */ fun storePower(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, power) + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, powerUnsafe) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt index 4b29dd22f4..da05bcf3d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt @@ -11,7 +11,14 @@ import org.bukkit.block.Block import org.bukkit.block.BlockState import org.bukkit.block.data.BlockData -class BlockSnapshot(val world: World, val x: Int, val y: Int, val z: Int, val type: Material, val data: BlockData) { +class BlockSnapshot( + val world: World, + val x: Int, + val y: Int, + val z: Int, + val type: Material, + val data: BlockData +) { val state: BlockState? get() { return runBlocking { getBukkitBlockState(block, false) } } @@ -22,6 +29,8 @@ class BlockSnapshot(val world: World, val x: Int, val y: Int, val z: Int, val ty val customBlock: CustomBlock? get() = CustomBlocks.getByBlockData(data) + val redstonePower: Int get() = block.blockPower + companion object { fun ChunkSnapshot.getBlockSnapshot(x: Int, y: Int, z: Int): BlockSnapshot? { if (x shr 4 != getX()) return null @@ -33,7 +42,9 @@ class BlockSnapshot(val world: World, val x: Int, val y: Int, val z: Int, val ty val localX = x - chunkOriginX val localZ = z - chunkOriginZ - return BlockSnapshot(Bukkit.getWorld(worldName)!!, x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) + val world = Bukkit.getWorld(worldName)!! + + return BlockSnapshot(world, x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) } fun Block.snapshot(): BlockSnapshot = BlockSnapshot(world, x, y, z, type, blockData) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index 948d80fa79..50f2b29879 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -4,10 +4,14 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Chunk +import org.bukkit.event.block.BlockBreakEvent import java.util.concurrent.ConcurrentLinkedQueue class ChunkTransportNetwork( @@ -42,6 +46,21 @@ class ChunkTransportNetwork( } + fun processBlockChange(event: BlockBreakEvent) { + val block = event.block + + val key = toBlockKey(block.x, block.y, block.z) + val snapshot = block.snapshot() + + processBlockChange(key, snapshot) + } + + fun processBlockChange(key: Long, new: BlockSnapshot) { + powerGrid.processBlockChange(key, new) + pipeGrid.processBlockChange(key, new) + gasGrid.processBlockChange(key, new) + } + private fun getExtractorData(chunk: Chunk): ExtractorData { val extractors = chunk.persistentDataContainer.get(NamespacedKeys.EXTRACTOR_DATA, ExtractorData) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt index d1d5fa6d98..78a82c7bc6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt @@ -15,18 +15,13 @@ abstract class Grid(val network: ChunkTransportNetwork) { val nodes: ConcurrentHashMap = ConcurrentHashMap() val world get() = network.chunk.world - val grids: Nothing = TODO("Grid system") +// val grids: Nothing = TODO("Grid system") /** * **/ open fun setup() {} - /** - * - **/ - abstract fun isNode(block: BlockSnapshot): Boolean - /** * Handle the creation / loading of the node into memory * @@ -34,7 +29,7 @@ abstract class Grid(val network: ChunkTransportNetwork) { **/ abstract fun loadNode(block: BlockSnapshot): GridNode? - abstract fun processBlockChange(previous: BlockSnapshot, new: BlockSnapshot) + abstract fun processBlockChange(key: Long, new: BlockSnapshot) /** * @@ -82,8 +77,6 @@ abstract class Grid(val network: ChunkTransportNetwork) { val snapshot = getBlockSnapshotAsync(network.chunk.world, realX, realY, realZ) ?: continue - if (!isNode(snapshot)) continue - val node = loadNode(snapshot) ?: continue nodes[toBlockKey(realX, realY, realZ)] = node diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt index 07db3129d6..5f3a1ad30b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -5,27 +5,29 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultibl import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.node.general.GateNode import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.features.transport.node.general.LinearNode +import net.horizonsend.ion.server.features.transport.node.power.MergeNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.power.SplitterNode +import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp import org.bukkit.Material import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { - private val poweredMultiblockEntities = ConcurrentHashMap() + val poweredMultiblockEntities = ConcurrentHashMap() + val extractors = ConcurrentHashMap() override fun setup() { collectPowerMultiblockEntities() } - override fun isNode(block: BlockSnapshot): Boolean = when (block.type) { - Material.END_ROD, Material.SPONGE, Material.IRON_BLOCK, Material.REDSTONE_BLOCK -> true - else -> false - } - override fun loadNode(block: BlockSnapshot): GridNode? { val x = block.x val y = block.y @@ -33,7 +35,7 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { return when { // Extract power from storage - block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z) + block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } // Add power to storage block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) @@ -45,31 +47,54 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { block.type == Material.SPONGE -> JunctionNode(this, x, y, z) // Merge node behavior - block.type == Material.IRON_BLOCK -> MergeNode() - block.type == Material.REDSTONE_BLOCK -> MergeNode() + block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) + block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) // Split power evenly - block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode() + block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) // Redstone controlled gate - block.type.isRedstoneLamp -> GateNode() + block.type.isRedstoneLamp -> GateNode(this, x, y, z) // Power flow meter - block.type == Material.OBSERVER -> PowerFlowMeter() + block.type == Material.OBSERVER -> PowerFlowMeter(this, x, y, z) else -> null } } - override fun processBlockChange(previous: BlockSnapshot, new: BlockSnapshot) { + override fun processBlockChange(key: Long, new: BlockSnapshot) { + val newNode = loadNode(new) + + val previousNode = nodes[key] + + if (previousNode == null) { + nodes[key] = newNode ?: return + newNode.collectNeighbors() + newNode.notifyNeighbors() + + return + } + + if (newNode == null) { + removeNode(key) + return + } + previousNode.replace(newNode) } fun removeNode(key: Long) { + nodes.remove(key) + } + val tickExecutor = IntervalExecutor(20) { + for ((key, extractor) in extractors.filterValues { it.transferableNeighbors.isNotEmpty() }) { + extractor.startStep().step() + } } override fun tick() { - TODO("Not yet implemented") + tickExecutor() } private fun collectPowerMultiblockEntities() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt index c42b3e58bb..fec330c27c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt @@ -10,7 +10,8 @@ abstract class ExtractorNode( override val x: Int, override val y: Int, override val z: Int, - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() ) : GridNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + abstract fun getExtractableInventories(): Collection> } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt index d56f2a9f8a..49391c008f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.setOrRemove @@ -37,6 +38,24 @@ interface GridNode { } } + /** + * Notify neighbors of this node's existence + **/ + fun notifyNeighbors() { + // In every adjacent direction + for (direction in ADJACENT_BLOCK_FACES) { + val newX = x + direction.modX + val newY = y + direction.modY + val newZ = z + direction.modZ + + // All nodes should already be collected + val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue + + possibleNode.transferableNeighbors.clear() + possibleNode.collectNeighbors() + } + } + /** * Notifies this node of a changed neighbor * @@ -54,6 +73,8 @@ interface GridNode { /** * Whether a power transfer may take place between these two nodes + * + * Used when initially building relations **/ fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean @@ -74,4 +95,6 @@ interface GridNode { parentGrid.nodes.setOrRemove(key, new) } } + + fun processStep(step: Step) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt new file mode 100644 index 0000000000..d7da00238a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt @@ -0,0 +1,24 @@ +package net.horizonsend.ion.server.features.transport.node.general + +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class GateNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, +) : GridNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + return true + } + + override fun processStep(step: Step) { + TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 3394cca28c..05b5bf5296 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -3,8 +3,12 @@ package net.horizonsend.ion.server.features.transport.node.general import net.horizonsend.ion.server.features.transport.grid.Grid import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransferStatus import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ThreadLocalRandom +import kotlin.random.asKotlinRandom /** * An omnidirectional node @@ -14,9 +18,28 @@ class JunctionNode( override val x: Int, override val y: Int, override val z: Int, - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() ) : GridNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - return node !is ExtractorNode + return node !is ExtractorNode<*> + } + + override fun processStep(step: Step) { + val neighbor = transferableNeighbors + .entries + .filter { it.key != step.direction } + .randomOrNull(ThreadLocalRandom.current().asKotlinRandom()) + + if (neighbor == null) { + step.status = TransferStatus.BLOCKED + + return + } + + val (offset, node) = neighbor + + step.direction = offset + step.currentNode = node } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index b869794005..5be98279ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.transport.grid.Grid import net.horizonsend.ion.server.features.transport.node.Consolidatable import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.faces @@ -37,6 +38,10 @@ class LinearNode( return offset.axis == axis } + override fun processStep(step: Step) { + TODO("Not yet implemented") + } + override fun consolidate() { for (face in this.axis.faces) { val node = getNeighbor(face) ?: continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt new file mode 100644 index 0000000000..4db6ff0801 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -0,0 +1,25 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.ExtractorNode +import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class MergeNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, +) : GridNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + return node !is ExtractorNode<*> + } + + override fun processStep(step: Step) { + TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 0ddaa00a93..5e53910b2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -2,25 +2,31 @@ package net.horizonsend.ion.server.features.transport.node.power import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.container.ResourceContainer import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.PowerStep +import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.World import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap class PowerExtractorNode( - parentGrid: Grid, + override val parentGrid: PowerGrid, x: Int, y: Int, z: Int, - transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap(), val solarPanel: Boolean = isSolarPanel(parentGrid, x, y, z) -) : ExtractorNode(parentGrid, x, y, z, transferableNeighbors) { +) : ExtractorNode(parentGrid, x, y, z) { var lastTicked: Long = System.currentTimeMillis() + override fun getExtractableInventories(): Collection> { + TODO("Not yet implemented") + } + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { // Don't send power to other extractors if (node is PowerExtractorNode) return false @@ -35,7 +41,6 @@ class PowerExtractorNode( fun tickSolarPanel(): Int { val time = System.currentTimeMillis() val deltaMs = time - lastTicked - lastTicked = time val deltaSeconds = deltaMs / 1000.0 return getPower(deltaSeconds) @@ -49,6 +54,21 @@ class PowerExtractorNode( return (power * delta).toInt() } + override fun processStep(step: Step) { + println("Stepping extractor") + } + + fun startStep(): Step { + val direction = transferableNeighbors.keys().toList().random() + + return PowerStep( + grid = parentGrid, + origin = null, + direction = direction, + this + ) + } + companion object { fun isSolarPanel(parentGrid: Grid, x: Int, y: Int, z: Int): Boolean = runBlocking { val aboveOne = getBlockSnapshotAsync(parentGrid.world, x, y + 1, z, false) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt new file mode 100644 index 0000000000..8e746637c4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -0,0 +1,29 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class PowerFlowMeter( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, +) : GridNode, PowerNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + + + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + return true + } + + override fun processStep(step: Step) { + TODO("Not yet implemented") + } + + override val multiblocks: MutableList + get() = TODO("Not yet implemented") +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 1cceb7c0f0..3e37398fbb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,24 +1,44 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.PowerGrid import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransferStatus import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class PowerInputNode( - override val parentGrid: Grid, + override val parentGrid: PowerGrid, override val x: Int, override val y: Int, override val z: Int, - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap(), - override val multiblocks: Collection ) : GridNode, PowerNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + override val multiblocks: MutableList = getNeighboringMultiblocks() + /** * Gets the multiblocks to which this can input power **/ - suspend fun getMultiblocks(): Collection = TODO() + fun getNeighboringMultiblocks(): MutableList { + val multiblocks = mutableListOf() + + for ((offsetX, offsetY, offsetZ) in offsets) { + val x = this.x + offsetX + val y = this.y + offsetY + val z = this.z + offsetZ + + val key = toBlockKey(x, y, z) + + val multi = parentGrid.poweredMultiblockEntities[key] ?: continue + + multiblocks.add(multi) + } + + return multiblocks + } override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { // May only accept power @@ -40,4 +60,10 @@ class PowerInputNode( Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), ) } + + override fun processStep(step: Step) { + step.currentNode = this + step.status = TransferStatus.COMPLETE +// TODO("Not yet implemented") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt index 00bba1da7b..86973c5c81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt @@ -6,5 +6,5 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultibl * **/ interface PowerNode { - val multiblocks: Collection + val multiblocks: MutableList } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt new file mode 100644 index 0000000000..09091271aa --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt @@ -0,0 +1,24 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.step.Step +import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap + +class SplitterNode( + override val parentGrid: Grid, + override val x: Int, + override val y: Int, + override val z: Int, +) : GridNode { + override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() + + override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { + return true + } + + override fun processStep(step: Step) { + TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt new file mode 100644 index 0000000000..c55ceaf2e0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.transport.step + +import net.horizonsend.ion.server.features.transport.container.NamespacedResourceContainer +import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.node.GridNode +import org.bukkit.block.BlockFace + +class PowerStep( + override val grid: PowerGrid, + override val origin: NamespacedResourceContainer?, + direction: BlockFace, + currentNode: GridNode +) : Step(grid, origin, direction, currentNode) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt new file mode 100644 index 0000000000..19ed991266 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -0,0 +1,58 @@ +package net.horizonsend.ion.server.features.transport.step + +import net.horizonsend.ion.server.features.transport.container.ResourceContainer +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.debugAudience +import net.horizonsend.ion.server.miscellaneous.utils.highlightBlock +import org.bukkit.block.BlockFace + +abstract class Step( + open val grid: Grid, + open val origin: ResourceContainer<*>?, + var direction: BlockFace, + var currentNode: GridNode +) { + var status: TransferStatus = TransferStatus.STEPPING + + var children = mutableSetOf() + + var depth: Int = 0 + + fun step() { + depth++ + + if (depth >= MAX_STEP_DEPTH) return + + debugAudience.highlightBlock(Vec3i(currentNode.x, currentNode.y, currentNode.z), 50L) + + when (status) { + TransferStatus.COMPLETE -> return + TransferStatus.BLOCKED -> return + TransferStatus.SPLIT -> stepChildren() + TransferStatus.STEPPING -> step() + } + } + + private fun stepChildren() { + val iterator = children.iterator() + + while (iterator.hasNext()) { + val child = iterator.next() + + // Remove finished children + if (child.status == TransferStatus.COMPLETE || child.status == TransferStatus.BLOCKED) { + iterator.remove() + + continue + } + + child.step() + } + } + + companion object { + const val MAX_STEP_DEPTH = 25 + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt new file mode 100644 index 0000000000..28b311b0ac --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.transport.step + +enum class TransferStatus { + STEPPING, + SPLIT, + BLOCKED, + COMPLETE +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index f1b148069b..8c6c731cbe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -9,6 +9,7 @@ import net.minecraft.world.level.chunk.LevelChunkSection import org.bukkit.Chunk import org.bukkit.World import org.bukkit.event.EventHandler +import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent @@ -77,8 +78,16 @@ class IonChunk(val inner: Chunk) { unregisterChunk(event.chunk) } + @EventHandler + fun onBlockBreak(event: BlockBreakEvent) { + val ionChunk = event.block.chunk.ion() + ionChunk.transportNetwork.processBlockChange(event) + } + /** * Handles the creation, registration and loading of the chunk in the IonWorld + * + * It is imperative that every exception generated be handled **/ private fun registerChunk(chunk: Chunk): IonChunk { val ionWorld = chunk.world.ion @@ -112,4 +121,8 @@ class IonChunk(val inner: Chunk) { fun Chunk.ion(): IonChunk = this.world.ion.getChunk(chunkKey)!! } + + override fun toString(): String { + return "IonChunk[$x, $z]" + } } From 2491228a7eeb68d2bb6d7ad5e601b13da3389fa5 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 24 Apr 2024 02:13:03 -0500 Subject: [PATCH 021/500] fix upstream changes --- .../features/multiblock/ChunkMultiblockManager.kt | 10 +++++----- .../ion/server/features/transport/step/Step.kt | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 86a0c3da79..4edf69365d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType.LIST +import org.bukkit.persistence.PersistentDataType import org.slf4j.LoggerFactory import java.util.concurrent.ConcurrentHashMap @@ -107,9 +107,9 @@ class ChunkMultiblockManager(val chunk: IonChunk) { private fun saveMultiblocks() = Multiblocks.multiblockCoroutineScope.launch { val array = multiblockEntities.map { (_, entity) -> PersistentMultiblockData.toPrimitive(entity.store(), chunk.inner.persistentDataContainer.adapterContext) - } + }.toTypedArray() - chunk.inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, LIST.dataContainers(), array) + chunk.inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) chunk.inner.minecraft.isUnsaved = true } @@ -118,7 +118,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { **/ private fun loadMultiblocks() { val serialized = try { - chunk.inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, LIST.dataContainers()) ?: return + chunk.inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return } catch (e: IllegalArgumentException) { log.warn("Could not load chunks multiblocks for $chunk") if (e.message == "The found tag instance (NBTTagList) cannot store List") { @@ -127,7 +127,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { chunk.inner.persistentDataContainer.remove(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES) } - listOf() + arrayOf() } for (serializedMultiblockData in serialized) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index 19ed991266..318070343e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.step +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.container.ResourceContainer import net.horizonsend.ion.server.features.transport.grid.Grid import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import net.horizonsend.ion.server.miscellaneous.utils.highlightBlock import org.bukkit.block.BlockFace abstract class Step( From 8059077adb3a32ecd07046e813e032fe2ba015fa Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 24 Apr 2024 13:17:21 -0500 Subject: [PATCH 022/500] delete old space world system --- .../net/horizonsend/ion/server/command/space/StarCommand.kt | 1 - .../ion/server/features/ai/spawning/AISpawningUtils.kt | 2 ++ .../kotlin/net/horizonsend/ion/server/features/space/Space.kt | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt index 01ab654918..e6add07e3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/space/StarCommand.kt @@ -16,7 +16,6 @@ import net.horizonsend.ion.server.features.space.body.CachedStar import net.horizonsend.ion.server.features.space.body.OrbitingCelestialBody import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.features.space.SpaceWorlds import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.orNull import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt index 256495a81c..5fe8f27a19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt @@ -17,6 +17,8 @@ import net.horizonsend.ion.server.features.starship.active.ActiveControlledStars import net.horizonsend.ion.server.features.starship.control.controllers.Controller import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.modules.AISinkMessageFactory +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt index e4922418dd..74df96ee02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt @@ -19,8 +19,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.isWater import net.horizonsend.ion.server.miscellaneous.utils.listen import net.horizonsend.ion.server.miscellaneous.utils.optional @@ -241,6 +239,7 @@ object Space : IonServerComponent() { databaseId = starId, name = starName, spaceWorldName = spaceWorldName, + spaceWorldName = spaceWorldName, location = Vec3i(starX, starY, starZ), size = starSize, seed = starSeed, From ae4edd63113142931be236afc9f35b9f8805e3e2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 28 Apr 2024 12:51:20 -0500 Subject: [PATCH 023/500] start reworking node scheme --- .../server/command/admin/IonChunkCommand.kt | 5 +- .../multiblock/util/AsyncBlockUtils.kt | 11 +++ .../transport/ChunkTransportNetwork.kt | 26 ++++-- .../extractors/PersistentExtractorData.kt | 10 --- .../server/features/transport/grid/Grid.kt | 21 +++-- .../transport/grid/NamespaceTransferGrid.kt | 19 ---- .../features/transport/grid/PowerGrid.kt | 87 ++++++++++++++----- .../features/transport/node/GridNode.kt | 25 ++---- .../features/transport/node/TransportNode.kt | 38 ++++++++ .../transport/node/power/SpongeNode.kt | 23 +++++ .../ion/server/features/world/IonChunk.kt | 9 +- .../server/miscellaneous/utils/Collections.kt | 12 +++ .../utils/coordinates/NewBlockKey.kt | 6 +- 13 files changed, 201 insertions(+), 91 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 1c2833ca2d..1f775e2ed4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,6 +4,7 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock @@ -63,8 +64,10 @@ object IonChunkCommand : SLCommand() { else -> fail { "invalid network" } } + sender.information("${grid.nodes.size} total nodes.") + grid.nodes.forEach { (t, u) -> - val vec = toVec3i(u.key) + val vec = toVec3i(t) sender.highlightBlock(vec, 50L) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index dce5db897a..581393765f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -6,6 +6,9 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Deferred import kotlinx.coroutines.future.asDeferred import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.loadChunkAsync import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft @@ -42,6 +45,14 @@ suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChun return getChunkSnapshotAsync(world, x, z, loadChunks)?.getBlockSnapshot(x, y, z) } +/** Retrieves a snapshot of an async block */ +suspend fun getBlockSnapshotAsync(world: World, key: Long, loadChunks: Boolean = false): BlockSnapshot? { + val x = getX(key) + val y = getY(key) + val z = getZ(key) + return getChunkSnapshotAsync(world, x, z, loadChunks)?.getBlockSnapshot(x, y, z) +} + suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } suspend fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt index 50f2b29879..c703be8436 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Chunk import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPlaceEvent import java.util.concurrent.ConcurrentLinkedQueue class ChunkTransportNetwork( @@ -46,19 +47,32 @@ class ChunkTransportNetwork( } - fun processBlockChange(event: BlockBreakEvent) { + fun processBlockRemoval(event: BlockBreakEvent) { + val block = event.block + val key = toBlockKey(block.x, block.y, block.z) + + processBlockRemoval(key) + } + + fun processBlockAdditon(event: BlockPlaceEvent) { val block = event.block val key = toBlockKey(block.x, block.y, block.z) val snapshot = block.snapshot() - processBlockChange(key, snapshot) + processBlockAddition(key, snapshot) + } + + fun processBlockRemoval(key: Long) { + powerGrid.processBlockRemoval(key) + pipeGrid.processBlockRemoval(key) + gasGrid.processBlockRemoval(key) } - fun processBlockChange(key: Long, new: BlockSnapshot) { - powerGrid.processBlockChange(key, new) - pipeGrid.processBlockChange(key, new) - gasGrid.processBlockChange(key, new) + fun processBlockAddition(key: Long, new: BlockSnapshot) { + powerGrid.processBlockAddition(key, new) + pipeGrid.processBlockAddition(key, new) + gasGrid.processBlockAddition(key, new) } private fun getExtractorData(chunk: Chunk): ExtractorData { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt deleted file mode 100644 index 011516e86b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/extractors/PersistentExtractorData.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.transport.extractors - -class PersistentExtractorData( - val x: Int, - val y: Int, - val z: Int, - -) { - -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt index 78a82c7bc6..c31d3bbca5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt @@ -7,12 +7,12 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.Consolidatable -import net.horizonsend.ion.server.features.transport.node.GridNode +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import java.util.concurrent.ConcurrentHashMap abstract class Grid(val network: ChunkTransportNetwork) { - val nodes: ConcurrentHashMap = ConcurrentHashMap() + val nodes: ConcurrentHashMap = ConcurrentHashMap() val world get() = network.chunk.world // val grids: Nothing = TODO("Grid system") @@ -27,9 +27,10 @@ abstract class Grid(val network: ChunkTransportNetwork) { * * Inheritors may choose to save persistent data, or not **/ - abstract fun loadNode(block: BlockSnapshot): GridNode? + abstract fun loadNode(block: BlockSnapshot) - abstract fun processBlockChange(key: Long, new: BlockSnapshot) + abstract fun processBlockRemoval(key: Long) + abstract fun processBlockAddition(key: Long, new: BlockSnapshot) /** * @@ -42,7 +43,7 @@ abstract class Grid(val network: ChunkTransportNetwork) { fun build() = network.scope.launch { collectAllNodes().join() collectNeighbors() - consolidateNodes() + finalizeNodes() buildGraph() } @@ -77,9 +78,7 @@ abstract class Grid(val network: ChunkTransportNetwork) { val snapshot = getBlockSnapshotAsync(network.chunk.world, realX, realY, realZ) ?: continue - val node = loadNode(snapshot) ?: continue - - nodes[toBlockKey(realX, realY, realZ)] = node + loadNode(snapshot) } } } @@ -89,7 +88,7 @@ abstract class Grid(val network: ChunkTransportNetwork) { * Get the neighbors of a node **/ private fun collectNeighbors() { - nodes.values.forEach { node -> node.collectNeighbors() } +// nodes.values.forEach { node -> node.collectNeighbors() } } /** @@ -97,7 +96,7 @@ abstract class Grid(val network: ChunkTransportNetwork) { * * e.g. a straight section may be represented as a single node **/ - private fun consolidateNodes() { + private fun finalizeNodes() { nodes.forEach { (_, node) -> if (node is Consolidatable) node.consolidate() } @@ -110,7 +109,7 @@ abstract class Grid(val network: ChunkTransportNetwork) { //TODO } - fun getNode(x: Int, y: Int, z: Int): GridNode? { + fun getNode(x: Int, y: Int, z: Int): TransportNode? { val key = toBlockKey(x, y, z) return nodes[key] } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt deleted file mode 100644 index 0368d41ea7..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/NamespaceTransferGrid.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork -import org.bukkit.NamespacedKey - -abstract class NamespaceTransferGrid( - network: ChunkTransportNetwork, - vararg namespaces: NamespacedKey -) : Grid(network) { - val valueKeys = setOf(*namespaces) - - fun isTransferable(resourceKey: NamespacedKey): Boolean = valueKeys.contains(resourceKey) - - fun getTransferableResources(): Set = TODO() - - class ResourceContainer( - - ) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt index 5f3a1ad30b..a3e47e5421 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -1,22 +1,30 @@ package net.horizonsend.ion.server.features.transport.grid +import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.customblocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.node.general.GateNode -import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.power.MergeNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SplitterNode +import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor +import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp +import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo +import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull import org.bukkit.Material +import org.bukkit.block.BlockFace import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap @@ -28,12 +36,14 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { collectPowerMultiblockEntities() } - override fun loadNode(block: BlockSnapshot): GridNode? { + override fun loadNode(block: BlockSnapshot) { val x = block.x val y = block.y val z = block.z - return when { + val key = toBlockKey(x, y, z) + + when { // Extract power from storage block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } @@ -44,7 +54,7 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { block.type == Material.END_ROD -> LinearNode(this, x, y, z, block.data as Directional) // Omnidirectional wires - block.type == Material.SPONGE -> JunctionNode(this, x, y, z) + block.type == Material.SPONGE -> handleSpongeNode(key) // Merge node behavior block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) @@ -58,29 +68,20 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { // Power flow meter block.type == Material.OBSERVER -> PowerFlowMeter(this, x, y, z) - else -> null } } - override fun processBlockChange(key: Long, new: BlockSnapshot) { - val newNode = loadNode(new) - - val previousNode = nodes[key] - - if (previousNode == null) { - nodes[key] = newNode ?: return - newNode.collectNeighbors() - newNode.notifyNeighbors() - - return - } + override fun processBlockRemoval(key: Long) { + network.scope.launch { + val previousNode = nodes[key] - if (newNode == null) { - removeNode(key) - return + nodes.remove(key) } + } - previousNode.replace(newNode) + override fun processBlockAddition(key: Long, new: BlockSnapshot) { + loadNode(new) + //TODO } fun removeNode(key: Long) { @@ -104,4 +105,46 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { poweredMultiblockEntities[key] = entity } } + + private fun handleSpongeNode(position: Long) { + val neighbors = getNeighborNodes(position) + + when (neighbors.size) { + // New sponge node + 0 -> nodes[position] = SpongeNode(position) + // Consolidate into neighbor + 1 -> { + val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") + if (neighbor !is SpongeNode) return + + neighbor.positions += position + nodes[position] = neighbor + } + + // Join multiple neighbors together + in 2..6 -> { + // Get the larger + val spongeNeighbors: MutableMap = mutableMapOf() + neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } + + val largestNeighbor = spongeNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: return + + spongeNeighbors.forEach { + it.value.drainTo(largestNeighbor, this.nodes) + } + + largestNeighbor.positions.add(position) + + nodes[position] = largestNeighbor + } + } + } + + private fun getNeighborNodes(position: Long) = ADJACENT_BLOCK_FACES.associateWithNotNull { + val x = getX(position) + val y = getY(position) + val z = getZ(position) + + nodes[toBlockKey(x + it.modX, y + it.modY, z + it.modZ)] + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt index 49391c008f..f9662cb143 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt @@ -4,7 +4,6 @@ import net.horizonsend.ion.server.features.transport.grid.Grid import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.setOrRemove import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap @@ -22,20 +21,7 @@ interface GridNode { * Collects the neighbors of this node **/ fun collectNeighbors() { - // In every adjacent direction - for (direction in ADJACENT_BLOCK_FACES) { - val newX = x + direction.modX - val newY = y + direction.modY - val newZ = z + direction.modZ - - // All nodes should already be collected - val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue - - // Only add transferable nodes - if (!isTransferableTo(direction, possibleNode)) continue - transferableNeighbors[direction] = possibleNode - } } /** @@ -52,7 +38,6 @@ interface GridNode { val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue possibleNode.transferableNeighbors.clear() - possibleNode.collectNeighbors() } } @@ -89,11 +74,11 @@ interface GridNode { * Replace this node with another and update its neighbors **/ fun replace(new: GridNode?) { - for ((offset, neighbor) in transferableNeighbors) { - neighbor.neighborChanged(offset.oppositeFace, new) - - parentGrid.nodes.setOrRemove(key, new) - } +// for ((offset, neighbor) in transferableNeighbors) { +// neighbor.neighborChanged(offset.oppositeFace, new) +// +// parentGrid.nodes.setOrRemove(key, new) +// } } fun processStep(step: Step) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt new file mode 100644 index 0000000000..b679cf58e9 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -0,0 +1,38 @@ +package net.horizonsend.ion.server.features.transport.node + +/** + * Represents a single node, or step, in a transport grid + * + * A node may cover many blocks to avoid making unnecessary steps + **/ +interface TransportNode { + /** + * The positions occupied by the node + **/ + val positions: MutableSet + + /** + * The neighboring nodes that this node may transport to + **/ + val transferableNeighbors: MutableSet + + /** + * Returns whether this node may transport to the provided node + **/ + fun isTransferable(position: Long, node: TransportNode): Boolean + + + // Section Utility + + /** + * Drain all the positions and connections to the provided node + **/ + fun drainTo(new: TransportNode, nodes: MutableMap) { + new.positions.addAll(positions) + new.transferableNeighbors.addAll(transferableNeighbors) + + for (position in positions) { + nodes[position] = new + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt new file mode 100644 index 0000000000..d08f4c5f9c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -0,0 +1,23 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.node.TransportNode + +/** + * Represents a sponge [omnidirectional pipe] + * + * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly + **/ +class SpongeNode(origin: Long) : TransportNode { + override val positions: MutableSet = LongOpenHashSet() + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + + override fun isTransferable(position: Long, node: TransportNode): Boolean { + return true + } + + init { + positions.add(origin) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 8c6c731cbe..ce1b9bd532 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -10,6 +10,7 @@ import org.bukkit.Chunk import org.bukkit.World import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent @@ -81,7 +82,13 @@ class IonChunk(val inner: Chunk) { @EventHandler fun onBlockBreak(event: BlockBreakEvent) { val ionChunk = event.block.chunk.ion() - ionChunk.transportNetwork.processBlockChange(event) + ionChunk.transportNetwork.processBlockRemoval(event) + } + + @EventHandler + fun onBlockBreak(event: BlockPlaceEvent) { + val ionChunk = event.block.chunk.ion() + ionChunk.transportNetwork.processBlockAdditon(event) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index f77bee0c6f..0a3bdc49c1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -128,3 +128,15 @@ fun MutableMap.setOrRemove(key: K, value: V?) { set(key, value) } } + +fun > MutableMap.popMaxByOrNull(selector: (Map.Entry) -> R): Map.Entry? { + val max = maxByOrNull(selector) ?: return null + remove(max.key) + + return max +} + +inline fun Iterable.associateWithNotNull(valueSelector: (K) -> V?): Map { + @Suppress("UNCHECKED_CAST") + return associateWith(valueSelector).filterValues { it != null } as Map +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt index 180755863a..1654f502a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt @@ -7,4 +7,8 @@ import net.minecraft.core.BlockPos **/ fun toBlockKey(x: Int, y: Int, z: Int): Long = BlockPos.asLong(x, y, z) fun toBlockKey(vec3i: Vec3i): Long = BlockPos.asLong(vec3i.x, vec3i.y, vec3i.z) -fun toVec3i(key: Long): Vec3i = Vec3i(BlockPos.getX(key), BlockPos.getY(key), BlockPos.getZ(key)) +fun toVec3i(key: Long): Vec3i = Vec3i(getX(key), getY(key), getZ(key)) + +fun getX(key: Long) : Int = BlockPos.getX(key) +fun getY(key: Long) : Int = BlockPos.getY(key) +fun getZ(key: Long) : Int = BlockPos.getZ(key) From 927519d8fb2d52c189bd2cb84aeba31efad76eca Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 28 Apr 2024 22:36:07 -0500 Subject: [PATCH 024/500] continued --- .../server/command/admin/IonChunkCommand.kt | 5 ++- .../server/features/transport/grid/Grid.kt | 2 +- .../features/transport/grid/PowerGrid.kt | 20 ++-------- .../features/transport/node/NodeUtils.kt | 26 +++++++++++++ .../features/transport/node/TransportNode.kt | 38 ------------------- .../transport/node/nodes/MultiNode.kt | 28 ++++++++++++++ .../transport/node/nodes/TransportNode.kt | 17 +++++++++ .../transport/node/power/SpongeNode.kt | 25 +++++++++++- .../ion/server/features/world/IonChunk.kt | 1 + .../ion/server/miscellaneous/utils/Blocks.kt | 3 ++ 10 files changed, 106 insertions(+), 59 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 1f775e2ed4..b64336e7cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -64,11 +64,12 @@ object IonChunkCommand : SLCommand() { else -> fail { "invalid network" } } - sender.information("${grid.nodes.size} total nodes.") + sender.information("${grid.nodes.size} covered position(s).") + sender.information("${grid.nodes.values.distinct().size} unique node(s).") grid.nodes.forEach { (t, u) -> val vec = toVec3i(t) - + println(u) sender.highlightBlock(vec, 50L) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt index c31d3bbca5..26f15f8245 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.Consolidatable -import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import java.util.concurrent.ConcurrentHashMap diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt index a3e47e5421..623ef0bd8a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -7,18 +7,14 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.general.GateNode import net.horizonsend.ion.server.features.transport.node.general.LinearNode +import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.power.MergeNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SplitterNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor -import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo @@ -54,7 +50,7 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { block.type == Material.END_ROD -> LinearNode(this, x, y, z, block.data as Directional) // Omnidirectional wires - block.type == Material.SPONGE -> handleSpongeNode(key) + block.type == Material.SPONGE -> addSpongeNode(key) // Merge node behavior block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) @@ -106,8 +102,8 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { } } - private fun handleSpongeNode(position: Long) { - val neighbors = getNeighborNodes(position) + private fun addSpongeNode(position: Long) { + val neighbors = getNeighborNodes(position, nodes) when (neighbors.size) { // New sponge node @@ -139,12 +135,4 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { } } } - - private fun getNeighborNodes(position: Long) = ADJACENT_BLOCK_FACES.associateWithNotNull { - val x = getX(position) - val y = getY(position) - val z = getZ(position) - - nodes[toBlockKey(x + it.modX, y + it.modY, z + it.modZ)] - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt new file mode 100644 index 0000000000..1a5075f27c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.transport.node + +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.block.BlockFace + +fun getNeighborNodes(position: Long, nodes: Map, checkFaces: Set = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { + val x = getX(position) + val y = getY(position) + val z = getZ(position) + + nodes[toBlockKey(x + it.modX, y + it.modY, z + it.modZ)] +} + +fun getNeighborNodes(position: Long, nodes: Collection, checkFaces: Set = ADJACENT_BLOCK_FACES) = checkFaces.mapNotNull { + val x = getX(position) + val y = getY(position) + val z = getZ(position) + + toBlockKey(x + it.modX, y + it.modY, z + it.modZ).takeIf { key -> nodes.contains(key) } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt deleted file mode 100644 index b679cf58e9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ /dev/null @@ -1,38 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -/** - * Represents a single node, or step, in a transport grid - * - * A node may cover many blocks to avoid making unnecessary steps - **/ -interface TransportNode { - /** - * The positions occupied by the node - **/ - val positions: MutableSet - - /** - * The neighboring nodes that this node may transport to - **/ - val transferableNeighbors: MutableSet - - /** - * Returns whether this node may transport to the provided node - **/ - fun isTransferable(position: Long, node: TransportNode): Boolean - - - // Section Utility - - /** - * Drain all the positions and connections to the provided node - **/ - fun drainTo(new: TransportNode, nodes: MutableMap) { - new.positions.addAll(positions) - new.transferableNeighbors.addAll(transferableNeighbors) - - for (position in positions) { - nodes[position] = new - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt new file mode 100644 index 0000000000..0624ea5be6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt @@ -0,0 +1,28 @@ +package net.horizonsend.ion.server.features.transport.node.nodes + +/** + * A transport node that may cover many blocks to avoid making unnecessary steps + **/ +interface MultiNode : TransportNode { + /** + * The positions occupied by the node + **/ + val positions: MutableSet + + /** + * Returns whether the removal of the provided position should result in the splitting of a combined node + **/ + fun shouldSplit(position: Long, nodes: MutableMap): Boolean + + /** + * Drain all the positions and connections to the provided node + **/ + fun drainTo(new: MultiNode, nodes: MutableMap) { + new.positions.addAll(positions) + new.transferableNeighbors.addAll(transferableNeighbors) + + for (position in positions) { + nodes[position] = new + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt new file mode 100644 index 0000000000..313004f464 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -0,0 +1,17 @@ +package net.horizonsend.ion.server.features.transport.node.nodes + +/** + * Represents a single node, or step, in a transport grid + **/ +interface TransportNode { + + /** + * The neighboring nodes that this node may transport to + **/ + val transferableNeighbors: MutableSet + + /** + * Returns whether this node may transport to the provided node + **/ + fun isTransferable(position: Long, node: TransportNode): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index d08f4c5f9c..e5661e6f1f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -2,21 +2,42 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.nodes.MultiNode +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.ALL_DIRECTIONS +import org.bukkit.block.BlockFace /** * Represents a sponge [omnidirectional pipe] * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(origin: Long) : TransportNode { +class SpongeNode(origin: Long) : MultiNode { override val positions: MutableSet = LongOpenHashSet() + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() override fun isTransferable(position: Long, node: TransportNode): Boolean { return true } + override fun shouldSplit(position: Long, nodes: MutableMap): Boolean { + // If it covers a single or two blocks it cannot be split, simply remove it + if (positions.size < 2) return false + + // Get neighbors by blockface relation + val neighborPositions: Map = getNeighborNodes(position, nodes) + + // If covered removing this node results in an equal number of neighbors and positions then none are touching + if (neighborPositions.size == (positions.size - 1)) return true + + // All 26 adjacent directions + val adjacentNeighborPositions = getNeighborNodes(position, positions, ALL_DIRECTIONS) + + if (adjacentNeighborPositions) + } + init { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index ce1b9bd532..ce9c272c59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -57,6 +57,7 @@ class IonChunk(val inner: Chunk) { * Logic upon world save **/ fun save() { + transportNetwork.save() multiblockManager.save() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index 7deeff97f8..237a7f3a3c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -10,6 +10,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.WallSign +import java.util.EnumSet /** * @see getNMSBlockSateSafe @@ -93,6 +94,8 @@ val CARDINAL_BLOCK_FACES: Set = ImmutableSet.of( BlockFace.WEST ) +val ALL_DIRECTIONS: Set = EnumSet.complementOf(EnumSet.of(BlockFace.SELF)) + val BlockFace.rightFace: BlockFace get() = when (this) { BlockFace.NORTH -> BlockFace.EAST From 72cba5ad0fd502dd1e0f84595590ff9c59e8f9f2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 29 Apr 2024 12:18:59 -0500 Subject: [PATCH 025/500] node serialization / deserialization --- .../multiblock/ChunkMultiblockManager.kt | 11 ++--- .../multiblock/entity/MultiblockEntity.kt | 11 +++-- .../features/transport/grid/PowerGrid.kt | 2 +- .../features/transport/node/NodeType.kt | 27 +++++++++-- .../node/{power => nodes}/SpongeNode.kt | 29 ++++++++---- .../transport/node/nodes/TransportNode.kt | 47 ++++++++++++++++++- .../persistence/NamespacedKeys.kt | 4 ++ .../persistence/PDCSerializable.kt | 18 +++++++ 8 files changed, 123 insertions(+), 26 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{power => nodes}/SpongeNode.kt (63%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 4edf69365d..e2416f6d43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import org.slf4j.LoggerFactory @@ -37,7 +37,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { * Logic upon the chunk being saved **/ fun save() { - saveMultiblocks() + saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) } init { @@ -98,19 +98,18 @@ class ChunkMultiblockManager(val chunk: IonChunk) { tickingMultiblockEntities[entity.locationKey] = entity } - if (save) saveMultiblocks() + if (save) saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) } /** * Save the multiblock data back into the chunk **/ - private fun saveMultiblocks() = Multiblocks.multiblockCoroutineScope.launch { + private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = Multiblocks.multiblockCoroutineScope.launch { val array = multiblockEntities.map { (_, entity) -> - PersistentMultiblockData.toPrimitive(entity.store(), chunk.inner.persistentDataContainer.adapterContext) + entity.serialize(adapterContext, entity.store()) }.toTypedArray() chunk.inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) - chunk.inner.minecraft.isUnsaved = true } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index e858397827..ddd4951b43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -18,19 +19,19 @@ import org.bukkit.block.Sign * * @param world The world this multiblock is in * - * @param type The type of multiblock this entity represents + * @param multiblock The type of multiblock this entity represents * * @param signDirection The direction to find the sign from the origin block (the block the sign is placed on) **/ abstract class MultiblockEntity( - val type: Multiblock, + val multiblock: Multiblock, var x: Int, var y: Int, var z: Int, var world: World, var signDirection: BlockFace -) { +): PDCSerializable { /** * Returns the origin of this multiblock as a Location **/ @@ -56,7 +57,7 @@ abstract class MultiblockEntity( * This data is serialized and stored on the chunk when not loaded. **/ fun store(): PersistentMultiblockData { - val store = PersistentMultiblockData(x, y, z, type, signDirection) + val store = PersistentMultiblockData(x, y, z, multiblock, signDirection) storeAdditionalData(store) return store @@ -74,7 +75,7 @@ abstract class MultiblockEntity( suspend fun isIntact(): Boolean { val sign = getSign() ?: return false - return type.signMatchesStructureAsync(sign) + return multiblock.signMatchesStructureAsync(sign) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt index 623ef0bd8a..a7f4b2d38c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -8,12 +8,12 @@ import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.general.GateNode import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.nodes.SpongeNode import net.horizonsend.ion.server.features.transport.node.power.MergeNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SplitterNode -import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index f5cea12347..b3f4aaf888 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,7 +1,26 @@ package net.horizonsend.ion.server.features.transport.node -enum class NodeType { - ORIGIN, - INTERMEDIATE, - DESTINATION +import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.node.nodes.SpongeNode +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode + +enum class NodeType(val clazz: Class) { + //POWER + SPONGE_NODE(SpongeNode::class.java), + + //GAS + + //ITEM + ; + + fun newInstance(): TransportNode { + return clazz.getDeclaredConstructor().newInstance() + } + + companion object { + val type = EnumDataType(NodeType::class.java) + private val byNode: Map, NodeType> = entries.associateBy { it.clazz } + + operator fun get(node: TransportNode): NodeType = byNode[node.javaClass] ?: throw NoSuchElementException("Unregistered node type ${node.javaClass.simpleName}!") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt similarity index 63% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt index e5661e6f1f..7346e9aca2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt @@ -1,19 +1,24 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.nodes import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.node.getNeighborNodes -import net.horizonsend.ion.server.features.transport.node.nodes.MultiNode -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ALL_DIRECTIONS import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType /** * Represents a sponge [omnidirectional pipe] * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(origin: Long) : MultiNode { +class SpongeNode() : MultiNode { + constructor(origin: Long) : this() { + positions.add(origin) + } + override val positions: MutableSet = LongOpenHashSet() override val transferableNeighbors: MutableSet = ObjectOpenHashSet() @@ -22,6 +27,15 @@ class SpongeNode(origin: Long) : MultiNode { return true } + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) + } + override fun shouldSplit(position: Long, nodes: MutableMap): Boolean { // If it covers a single or two blocks it cannot be split, simply remove it if (positions.size < 2) return false @@ -35,10 +49,7 @@ class SpongeNode(origin: Long) : MultiNode { // All 26 adjacent directions val adjacentNeighborPositions = getNeighborNodes(position, positions, ALL_DIRECTIONS) - if (adjacentNeighborPositions) - } - - init { - positions.add(origin) +// if (adjacentNeighborPositions) + return false } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt index 313004f464..3dc41b7e2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -1,9 +1,18 @@ package net.horizonsend.ion.server.features.transport.node.nodes +import kotlinx.serialization.SerializationException +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + /** * Represents a single node, or step, in a transport grid **/ -interface TransportNode { +interface TransportNode : PDCSerializable { + override val type: Companion get() = Companion /** * The neighboring nodes that this node may transport to @@ -14,4 +23,40 @@ interface TransportNode { * Returns whether this node may transport to the provided node **/ fun isTransferable(position: Long, node: TransportNode): Boolean + + /** + * Store additional required data in the serialized container + **/ + fun storeData(persistentDataContainer: PersistentDataContainer) + + /** + * Load required data from the serialized container + **/ + fun loadData(persistentDataContainer: PersistentDataContainer) + + companion object : PersistentDataType { + override fun getPrimitiveType() = PersistentDataContainer::class.java + override fun getComplexType() = TransportNode::class.java + + override fun toPrimitive(complex: TransportNode, context: PersistentDataAdapterContext): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + pdc.set(NODE_TYPE, NodeType.type, NodeType[complex]) + + complex.storeData(pdc) + + return pdc + } + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): TransportNode = try { + val type = primitive.get(NODE_TYPE, NodeType.type)!! + val instance = type.newInstance() + + instance.loadData(primitive) + + instance + } catch (e: Throwable) { + e.printStackTrace() + throw SerializationException("Error deserializing multiblock data!") + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index bdf8c3b295..7ac970b257 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -89,6 +89,10 @@ object NamespacedKeys { val PROCESSING_PROGRESS = key("processing_progress") + val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") + val NODE_COVERED_POSITIONS = key("node_covered_positions") + val NODE_TYPE = key("node_type") + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt new file mode 100644 index 0000000000..ff7b51179c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.miscellaneous.registrations.persistence + +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +interface PDCSerializable > { + val type: T + + fun serialize(adapterContext: PersistentDataAdapterContext, data: V): PersistentDataContainer { + return type.toPrimitive(data, adapterContext) + } + + fun store(destination: PersistentDataContainer, key: NamespacedKey, data: V) { + destination.set(key, type, data) + } +} From 65f810e9df716c27fac0ea0af229bea1ed820d43 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 29 Apr 2024 14:38:20 -0500 Subject: [PATCH 026/500] storing/ loading of node data, rename grids to networks --- .../server/command/admin/IonChunkCommand.kt | 8 +- .../multiblock/entity/MultiblockEntity.kt | 2 + .../type/autocrafter/AutoCrafterMultiblock.kt | 4 +- ...ortNetwork.kt => ChunkTransportManager.kt} | 42 ++--- .../{PowerGrid.kt => ChunkPowerNetwork.kt} | 13 +- .../server/features/transport/grid/Grid.kt | 116 ------------ .../transport/grid/TransportNetwork.kt | 172 ++++++++++++++++++ .../features/transport/node/ExtractorNode.kt | 4 +- .../features/transport/node/GridNode.kt | 8 +- .../transport/node/general/GateNode.kt | 4 +- .../transport/node/general/JunctionNode.kt | 4 +- .../transport/node/general/LinearNode.kt | 8 +- .../transport/node/nodes/TransportNode.kt | 2 +- .../transport/node/power/MergeNode.kt | 4 +- .../node/power/PowerExtractorNode.kt | 20 +- .../transport/node/power/PowerFlowMeter.kt | 4 +- .../transport/node/power/PowerInputNode.kt | 6 +- .../transport/node/power/SplitterNode.kt | 4 +- .../features/transport/step/PowerStep.kt | 6 +- .../server/features/transport/step/Step.kt | 4 +- .../ion/server/features/world/IonChunk.kt | 6 +- .../persistence/NamespacedKeys.kt | 9 +- 22 files changed, 258 insertions(+), 192 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ChunkTransportNetwork.kt => ChunkTransportManager.kt} (69%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{PowerGrid.kt => ChunkPowerNetwork.kt} (91%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index b64336e7cc..4bf82f723f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -53,14 +53,14 @@ object IonChunkCommand : SLCommand() { } @Subcommand("dump nodes") - @CommandCompletion("power|item|gas") + @CommandCompletion("power") /* |item|gas") */ fun dumpNodes(sender: Player, network: String) { val ionChunk = sender.chunk.ion() val grid = when (network) { - "power" -> ionChunk.transportNetwork.powerGrid - "item" -> ionChunk.transportNetwork.pipeGrid - "gas" -> ionChunk.transportNetwork.gasGrid + "power" -> ionChunk.transportNetwork.powerNetwork +// "item" -> ionChunk.transportNetwork.pipeGrid +// "gas" -> ionChunk.transportNetwork.gasGrid else -> fail { "invalid network" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index ddd4951b43..0cdab7c432 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -32,6 +32,8 @@ abstract class MultiblockEntity( var world: World, var signDirection: BlockFace ): PDCSerializable { + override val type: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion + /** * Returns the origin of this multiblock as a Location **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 2af472ba13..e8ef1dd069 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -139,7 +139,7 @@ abstract class AutoCrafterMultiblock( val recipeHolder: InventoryHolder = getRecipeHolder(sign) ?: return val output: InventoryHolder = getOutput(sign) ?: return - // material data of each item in the recipe holder, used as the crafting grid + // material data of each item in the recipe holder, used as the crafting transportNetwork val grid: List = recipeHolder.inventory.map { it } val basePower = PowerMachines.getPower(sign, fast = true) @@ -168,7 +168,7 @@ abstract class AutoCrafterMultiblock( var requiredIngredients = 0 var matchedIngredients = 0 - // for each slot in the crafting grid, + // for each slot in the crafting transportNetwork, // if it's not null, // increment required ingredients to keep track of how many are needed, // and loop through the input inventory, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index c703be8436..112c23c21a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot -import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -15,7 +15,7 @@ import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent import java.util.concurrent.ConcurrentLinkedQueue -class ChunkTransportNetwork( +class ChunkTransportManager( val chunk: IonChunk, ) { // Each chunk gets a scope for parallelism @@ -23,28 +23,24 @@ class ChunkTransportNetwork( val extractorData = getExtractorData(chunk.inner) - val powerGrid = PowerGrid(this) - val pipeGrid = PowerGrid(this) // TODO - val gasGrid = PowerGrid(this) // TODO + val powerNetwork = ChunkPowerNetwork(this) +// val pipeGrid = ChunkPowerNetwork(this) // TODO +// val gasGrid = ChunkPowerNetwork(this) // TODO - init { - setup() - } - - private fun setup() { - powerGrid.setup() - pipeGrid.setup() - gasGrid.setup() + fun setup() { + powerNetwork.setup() +// pipeGrid.setup() +// gasGrid.setup() } fun tick() { - scope.launch { powerGrid.tick() } - scope.launch { pipeGrid.tick() } - scope.launch { gasGrid.tick() } + scope.launch { powerNetwork.tick() } +// scope.launch { pipeGrid.tick() } +// scope.launch { gasGrid.tick() } } fun save() { - + powerNetwork.save(chunk.inner.persistentDataContainer.adapterContext) } fun processBlockRemoval(event: BlockBreakEvent) { @@ -64,15 +60,15 @@ class ChunkTransportNetwork( } fun processBlockRemoval(key: Long) { - powerGrid.processBlockRemoval(key) - pipeGrid.processBlockRemoval(key) - gasGrid.processBlockRemoval(key) + powerNetwork.processBlockRemoval(key) +// pipeGrid.processBlockRemoval(key) +// gasGrid.processBlockRemoval(key) } fun processBlockAddition(key: Long, new: BlockSnapshot) { - powerGrid.processBlockAddition(key, new) - pipeGrid.processBlockAddition(key, new) - gasGrid.processBlockAddition(key, new) + powerNetwork.processBlockAddition(key, new) +// pipeGrid.processBlockAddition(key, new) +// gasGrid.processBlockAddition(key, new) } private fun getExtractorData(chunk: Chunk): ExtractorData { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index a7f4b2d38c..2b0c682f81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.customblocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.general.GateNode import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes @@ -14,20 +14,24 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNo import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SplitterNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull import org.bukkit.Material +import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap -class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { +class ChunkPowerNetwork(manager: ChunkTransportManager) : TransportNetwork(manager) { val poweredMultiblockEntities = ConcurrentHashMap() val extractors = ConcurrentHashMap() + override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT + override fun setup() { collectPowerMultiblockEntities() } @@ -68,10 +72,11 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { } override fun processBlockRemoval(key: Long) { - network.scope.launch { + manager.scope.launch { val previousNode = nodes[key] nodes.remove(key) + //TODO check for splits } } @@ -95,7 +100,7 @@ class PowerGrid(network: ChunkTransportNetwork) : Grid(network) { } private fun collectPowerMultiblockEntities() { - network.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> + manager.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> if (entity !is PoweredMultiblockEntity) return@forEach poweredMultiblockEntities[key] = entity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt deleted file mode 100644 index 26f15f8245..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ /dev/null @@ -1,116 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import kotlinx.coroutines.Job -import kotlinx.coroutines.joinAll -import kotlinx.coroutines.launch -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.Consolidatable -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import java.util.concurrent.ConcurrentHashMap - -abstract class Grid(val network: ChunkTransportNetwork) { - val nodes: ConcurrentHashMap = ConcurrentHashMap() - val world get() = network.chunk.world - -// val grids: Nothing = TODO("Grid system") - - /** - * - **/ - open fun setup() {} - - /** - * Handle the creation / loading of the node into memory - * - * Inheritors may choose to save persistent data, or not - **/ - abstract fun loadNode(block: BlockSnapshot) - - abstract fun processBlockRemoval(key: Long) - abstract fun processBlockAddition(key: Long, new: BlockSnapshot) - - /** - * - **/ - abstract fun tick() - - /** - * Builds the grid TODO better documentation - **/ - fun build() = network.scope.launch { - collectAllNodes().join() - collectNeighbors() - finalizeNodes() - buildGraph() - } - - /** - * - **/ - private fun collectAllNodes(): Job = network.scope.launch { - // Parallel collect the nodes of each section - network.chunk.sections.map { (y, _) -> - launch { collectSectionNodes(y) } - }.joinAll() - } - - /** - * Collect all nodes in this chunk section - * - * Iterate the section for possible nodes, handle creation - **/ - suspend fun collectSectionNodes(sectionY: Int) { - val originX = network.chunk.originX - val originY = sectionY.shl(4) - network.chunk.inner.world.minHeight - val originZ = network.chunk.originZ - - for (x: Int in 0..15) { - val realX = originX + x - - for (y: Int in 0..15) { - val realY = originY + y - - for (z: Int in 0..15) { - val realZ = originZ + z - - val snapshot = getBlockSnapshotAsync(network.chunk.world, realX, realY, realZ) ?: continue - - loadNode(snapshot) - } - } - } - } - - /** - * Get the neighbors of a node - **/ - private fun collectNeighbors() { -// nodes.values.forEach { node -> node.collectNeighbors() } - } - - /** - * Consolidates network nodes where possible - * - * e.g. a straight section may be represented as a single node - **/ - private fun finalizeNodes() { - nodes.forEach { (_, node) -> - if (node is Consolidatable) node.consolidate() - } - } - - /** - * - **/ - private fun buildGraph() { - //TODO - } - - fun getNode(x: Int, y: Int, z: Int): TransportNode? { - val key = toBlockKey(x, y, z) - return nodes[key] - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt new file mode 100644 index 0000000000..868f5fbaaa --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt @@ -0,0 +1,172 @@ +package net.horizonsend.ion.server.features.transport.grid + +import com.manya.pdc.base.MapDataType +import kotlinx.coroutines.Job +import kotlinx.coroutines.joinAll +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.Consolidatable +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_LOCATIONS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.seconds +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType +import java.util.concurrent.ConcurrentHashMap +import java.util.stream.Collectors + +abstract class TransportNetwork(val manager: ChunkTransportManager) { + val nodes: ConcurrentHashMap = ConcurrentHashMap() + val world get() = manager.chunk.world + + val pdc get() = manager.chunk.inner.persistentDataContainer + + protected abstract val namespacedKey: NamespacedKey + +// val grids: Nothing = TODO("TransportNetwork system") + + init { + loadData() + } + + open fun setup() {} + + /** + * Handle the creation / loading of the node into memory + * + * Inheritors may choose to save persistent data, or not + **/ + abstract fun loadNode(block: BlockSnapshot) + + abstract fun processBlockRemoval(key: Long) + abstract fun processBlockAddition(key: Long, new: BlockSnapshot) + + companion object { + private val locationDataType = MapDataType( + Collectors.toMap({ it.key }, { it.value }), + PersistentDataType.LONG, + PersistentDataType.INTEGER + ) + } + + /** + * Load stored node data from the chunk + **/ + private fun loadData() { + val existing = pdc.get(POWER_TRANSPORT, PersistentDataType.TAG_CONTAINER) ?: return + + val nodeLocations = existing.get(NODE_LOCATIONS, locationDataType)!! + val nodeData = existing.get(NODES, PersistentDataType.TAG_CONTAINER_ARRAY)!!.map { TransportNode.fromPrimitive(it, pdc.adapterContext) } + + for ((locationKey, nodeIndex) in nodeLocations) { + nodes[locationKey] = nodeData[nodeIndex] + } + } + + fun save(adapterContext: PersistentDataAdapterContext) { + val container = adapterContext.newPersistentDataContainer() + + val serializedNodes = nodes.values.associateWith { nodes.values.indexOf(it) to it.serialize(adapterContext, it) } + //TODO find better implementation of storage + + val dataMap = nodes.map { (key, node) -> + key to serializedNodes[node]!!.first + }.toMap() + + container.set(NODE_LOCATIONS, locationDataType, dataMap) + container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.seconds().toTypedArray()) + + pdc.set(namespacedKey, PersistentDataType.TAG_CONTAINER, container) + + saveAdditional() + } + + open fun saveAdditional() {} + + /** + * + **/ + abstract fun tick() + + /** + * Builds the transportNetwork TODO better documentation + **/ + fun build() = manager.scope.launch { + collectAllNodes().join() + collectNeighbors() + finalizeNodes() + buildGraph() + } + + /** + * + **/ + private fun collectAllNodes(): Job = manager.scope.launch { + // Parallel collect the nodes of each section + manager.chunk.sections.map { (y, _) -> + launch { collectSectionNodes(y) } + }.joinAll() + } + + /** + * Collect all nodes in this chunk section + * + * Iterate the section for possible nodes, handle creation + **/ + suspend fun collectSectionNodes(sectionY: Int) { + val originX = manager.chunk.originX + val originY = sectionY.shl(4) - manager.chunk.inner.world.minHeight + val originZ = manager.chunk.originZ + + for (x: Int in 0..15) { + val realX = originX + x + + for (y: Int in 0..15) { + val realY = originY + y + + for (z: Int in 0..15) { + val realZ = originZ + z + + val snapshot = getBlockSnapshotAsync(manager.chunk.world, realX, realY, realZ) ?: continue + + loadNode(snapshot) + } + } + } + } + + /** + * Get the neighbors of a node + **/ + private fun collectNeighbors() { +// nodes.values.forEach { node -> node.collectNeighbors() } + } + + /** + * Consolidates network nodes where possible + * + * e.g. a straight section may be represented as a single node + **/ + private fun finalizeNodes() { + nodes.forEach { (_, node) -> + if (node is Consolidatable) node.consolidate() + } + } + + /** + * + **/ + private fun buildGraph() { + //TODO + } + + fun getNode(x: Int, y: Int, z: Int): TransportNode? { + val key = toBlockKey(x, y, z) + return nodes[key] + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt index fec330c27c..bc125123f6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap abstract class ExtractorNode( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt index f9662cb143..bfd682ec40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -8,7 +8,7 @@ import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap interface GridNode { - val parentGrid: Grid + val parentTransportNetwork: TransportNetwork val x: Int val y: Int val z: Int @@ -35,7 +35,7 @@ interface GridNode { val newZ = z + direction.modZ // All nodes should already be collected - val possibleNode = parentGrid.getNode(newX, newY, newZ) ?: continue + val possibleNode = parentTransportNetwork.getNode(newX, newY, newZ) ?: continue possibleNode.transferableNeighbors.clear() } @@ -77,7 +77,7 @@ interface GridNode { // for ((offset, neighbor) in transferableNeighbors) { // neighbor.neighborChanged(offset.oppositeFace, new) // -// parentGrid.nodes.setOrRemove(key, new) +// parentTransportNetwork.nodes.setOrRemove(key, new) // } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt index d7da00238a..ecdd8e92bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt @@ -1,13 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.general -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class GateNode( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 05b5bf5296..694eced762 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.general -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step @@ -14,7 +14,7 @@ import kotlin.random.asKotlinRandom * An omnidirectional node **/ class JunctionNode( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index 5be98279ca..15273bbc91 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.general import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.Consolidatable import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step @@ -15,7 +15,7 @@ import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap class LinearNode( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, @@ -23,13 +23,13 @@ class LinearNode( val occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) ) : GridNode, Consolidatable { constructor( - grid: Grid, + transportNetwork: TransportNetwork, x: Int, y: Int, z: Int, data: Directional, occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) - ) : this(grid, x, y, z, data.facing.axis, occupiedPositions) + ) : this(transportNetwork, x, y, z, data.facing.axis, occupiedPositions) override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt index 3dc41b7e2d..6c6cae92f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -9,7 +9,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType /** - * Represents a single node, or step, in a transport grid + * Represents a single node, or step, in a transport transportNetwork **/ interface TransportNode : PDCSerializable { override val type: Companion get() = Companion diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt index 4db6ff0801..ff580c5ae9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step @@ -8,7 +8,7 @@ import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class MergeNode( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 5e53910b2d..b9ec2f2966 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.transport.node.power import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.Grid -import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.PowerStep @@ -15,12 +15,12 @@ import org.bukkit.World import org.bukkit.block.BlockFace class PowerExtractorNode( - override val parentGrid: PowerGrid, + override val parentTransportNetwork: ChunkPowerNetwork, x: Int, y: Int, z: Int, - val solarPanel: Boolean = isSolarPanel(parentGrid, x, y, z) -) : ExtractorNode(parentGrid, x, y, z) { + val solarPanel: Boolean = isSolarPanel(parentTransportNetwork, x, y, z) +) : ExtractorNode(parentTransportNetwork, x, y, z) { var lastTicked: Long = System.currentTimeMillis() override fun getExtractableInventories(): Collection> { @@ -47,7 +47,7 @@ class PowerExtractorNode( } private fun getPower(delta: Double): Int { - val environment = parentGrid.world.environment + val environment = parentTransportNetwork.world.environment val power = 5.0 / if (environment == World.Environment.NORMAL) 1.0 else 2.0 @@ -62,7 +62,7 @@ class PowerExtractorNode( val direction = transferableNeighbors.keys().toList().random() return PowerStep( - grid = parentGrid, + transportNetwork = parentTransportNetwork, origin = null, direction = direction, this @@ -70,9 +70,9 @@ class PowerExtractorNode( } companion object { - fun isSolarPanel(parentGrid: Grid, x: Int, y: Int, z: Int): Boolean = runBlocking { - val aboveOne = getBlockSnapshotAsync(parentGrid.world, x, y + 1, z, false) - val aboveTwo = getBlockSnapshotAsync(parentGrid.world, x, y + 2, z, false) + fun isSolarPanel(parentTransportNetwork: TransportNetwork, x: Int, y: Int, z: Int): Boolean = runBlocking { + val aboveOne = getBlockSnapshotAsync(parentTransportNetwork.world, x, y + 1, z, false) + val aboveTwo = getBlockSnapshotAsync(parentTransportNetwork.world, x, y + 2, z, false) return@runBlocking aboveOne?.type == Material.DIAMOND_BLOCK && aboveTwo?.type == Material.DAYLIGHT_DETECTOR } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 8e746637c4..2a9b165ad1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -1,14 +1,14 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class PowerFlowMeter( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 3e37398fbb..f908e21faf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.TransferStatus @@ -11,7 +11,7 @@ import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class PowerInputNode( - override val parentGrid: PowerGrid, + override val parentTransportNetwork: ChunkPowerNetwork, override val x: Int, override val y: Int, override val z: Int, @@ -32,7 +32,7 @@ class PowerInputNode( val key = toBlockKey(x, y, z) - val multi = parentGrid.poweredMultiblockEntities[key] ?: continue + val multi = parentTransportNetwork.poweredMultiblockEntities[key] ?: continue multiblocks.add(multi) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt index 09091271aa..774b3a2b51 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt @@ -1,13 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class SplitterNode( - override val parentGrid: Grid, + override val parentTransportNetwork: TransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt index c55ceaf2e0..4e7c540b76 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt @@ -1,13 +1,13 @@ package net.horizonsend.ion.server.features.transport.step import net.horizonsend.ion.server.features.transport.container.NamespacedResourceContainer -import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import org.bukkit.block.BlockFace class PowerStep( - override val grid: PowerGrid, + override val transportNetwork: ChunkPowerNetwork, override val origin: NamespacedResourceContainer?, direction: BlockFace, currentNode: GridNode -) : Step(grid, origin, direction, currentNode) +) : Step(transportNetwork, origin, direction, currentNode) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index 318070343e..756622a0d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -2,14 +2,14 @@ package net.horizonsend.ion.server.features.transport.step import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.TransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.block.BlockFace abstract class Step( - open val grid: Grid, + open val transportNetwork: TransportNetwork, open val origin: ResourceContainer<*>?, var direction: BlockFace, var currentNode: GridNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index ce9c272c59..0c5a1cd20b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.world import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager -import net.horizonsend.ion.server.features.transport.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.minecraft @@ -37,13 +37,13 @@ class IonChunk(val inner: Chunk) { // - Explosion Reversal val multiblockManager = ChunkMultiblockManager(this) - val transportNetwork: ChunkTransportNetwork = ChunkTransportNetwork(this) + val transportNetwork: ChunkTransportManager = ChunkTransportManager(this) /** * Logic upon loading the chunk **/ fun onLoad() { - + transportNetwork.setup() } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 7ac970b257..46df77b9dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -37,7 +37,6 @@ object NamespacedKeys { val LOCKED = key("locked") val AMMO = key("Ammo") - val GAS = key("Gas") val CUSTOM_ITEM = key("CustomItem") val EDEN_FIX = key("EdenFix") val BIOME_FIX = key("BiomeFix") @@ -57,6 +56,11 @@ object NamespacedKeys { @Deprecated("") val ORE_CHECK = key("oreCheck") val POWER = key("power") + val GAS = key("Gas") + + val POWER_TRANSPORT = key("power_transport") + val GAS_TRANSPORT = key("gas_transport") + val ITEM_TRANSPORT = key("item_transport") val TUBE_BUTTONS = key("tube_buttons") val MATERIAL = key("material") @@ -93,6 +97,9 @@ object NamespacedKeys { val NODE_COVERED_POSITIONS = key("node_covered_positions") val NODE_TYPE = key("node_type") + val NODES = key("chunk_power_nodes") + val NODE_LOCATIONS = key("chunk_power_node_locations") + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs From 15327d78a0a4e745c933f2967032c29280dc618e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 29 Apr 2024 23:19:04 -0500 Subject: [PATCH 027/500] organization --- .../server/features/transport/grid/ChunkPowerNetwork.kt | 8 +++++--- .../server/features/transport/grid/TransportNetwork.kt | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index 2b0c682f81..e98e81c555 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -36,7 +36,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : TransportNetwork(manag collectPowerMultiblockEntities() } - override fun loadNode(block: BlockSnapshot) { + override fun createNodeFromBlock(block: BlockSnapshot) { val x = block.x val y = block.y val z = block.z @@ -81,7 +81,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : TransportNetwork(manag } override fun processBlockAddition(key: Long, new: BlockSnapshot) { - loadNode(new) + createNodeFromBlock(new) //TODO } @@ -128,14 +128,16 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : TransportNetwork(manag val spongeNeighbors: MutableMap = mutableMapOf() neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } + // Get the largest neighbor val largestNeighbor = spongeNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: return + // Merge all other connected nodes into the largest spongeNeighbors.forEach { it.value.drainTo(largestNeighbor, this.nodes) } + // Add this node largestNeighbor.positions.add(position) - nodes[position] = largestNeighbor } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt index 868f5fbaaa..374e843f53 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt @@ -41,7 +41,7 @@ abstract class TransportNetwork(val manager: ChunkTransportManager) { * * Inheritors may choose to save persistent data, or not **/ - abstract fun loadNode(block: BlockSnapshot) + abstract fun createNodeFromBlock(block: BlockSnapshot) abstract fun processBlockRemoval(key: Long) abstract fun processBlockAddition(key: Long, new: BlockSnapshot) @@ -134,7 +134,7 @@ abstract class TransportNetwork(val manager: ChunkTransportManager) { val snapshot = getBlockSnapshotAsync(manager.chunk.world, realX, realY, realZ) ?: continue - loadNode(snapshot) + createNodeFromBlock(snapshot) } } } From abebad2c5f051e49f94afe252bf305c86f260a70 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 30 Apr 2024 02:07:32 -0500 Subject: [PATCH 028/500] better(ish) deserialization --- .../multiblock/entity/MultiblockEntity.kt | 2 +- .../features/transport/node/NodeType.kt | 81 +++++++++++++++++-- .../transport/node/nodes/SpongeNode.kt | 5 -- .../transport/node/nodes/TransportNode.kt | 24 +++--- .../persistence/NamespacedKeys.kt | 1 + .../persistence/PDCSerializable.kt | 6 +- 6 files changed, 90 insertions(+), 29 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 0cdab7c432..3ef430bb9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -32,7 +32,7 @@ abstract class MultiblockEntity( var world: World, var signDirection: BlockFace ): PDCSerializable { - override val type: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion + override val serializationType: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion /** * Returns the origin of this multiblock as a Location diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index b3f4aaf888..5f9f918acc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,26 +1,91 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.node.nodes.SpongeNode import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.reflect.KClass +import kotlin.reflect.KProperty -enum class NodeType(val clazz: Class) { - //POWER - SPONGE_NODE(SpongeNode::class.java), +enum class NodeType(val javaClass: Class, val kotlinClass: KClass, registerDataLoaders: NodeType.() -> Unit = {}) { + // GENERAL + //TODO Extractor + //TODO Straight node for power and gas + //TODO Merge node - //GAS + // POWER + SPONGE_NODE(SpongeNode::class.java, SpongeNode::class, { + addDataLoader(SpongeNode::positions, NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, MutableSet::class.java) { LongOpenHashSet(it) } + }), + //TODO Power flow meter + //TODO Power input + //TODO Power Splitter - //ITEM + // GAS + //TODO pane node + + // ITEM + //TODO Sponge equivalent for glass color ; - fun newInstance(): TransportNode { - return clazz.getDeclaredConstructor().newInstance() + private val dataLoaders: MutableMap, DataLoader<*, *, *>> = mutableMapOf() + + fun addDataLoader( + property: KProperty, + storageKey: NamespacedKey, + dataType: PersistentDataType, + fieldDataClass: Class, + defaultValue: Z? = null, + complexTransform: (Z?) -> J + ) { + dataLoaders[property] = DataLoader(storageKey, dataType, fieldDataClass, defaultValue, complexTransform) + } + + fun load(additionalData: PersistentDataContainer): TransportNode { + val fields: Array> = dataLoaders.map { it.value.fieldDataClass }.toTypedArray() + val data: Array = dataLoaders.map { (_, loader) -> loader.get(additionalData) }.toTypedArray() + + return javaClass.getDeclaredConstructor(*fields).newInstance(data) + } + + init { + registerDataLoaders(this) } companion object { val type = EnumDataType(NodeType::class.java) - private val byNode: Map, NodeType> = entries.associateBy { it.clazz } + private val byNode: Map, NodeType> = entries.associateBy { it.javaClass } operator fun get(node: TransportNode): NodeType = byNode[node.javaClass] ?: throw NoSuchElementException("Unregistered node type ${node.javaClass.simpleName}!") } + + /** + * @param key The key that the data will be stored in + * @param dataType The persistent data type of the type + * @param fieldDataClass The Java class of the type of the field + * @param defaultValue The default value if none is found from serialization. If not provided, and no data is found, a serialization exception will occur + * @param complexTransform The transform applied to the value retrieved from the persistent data container + * + * @param J the final type + * @param T the serialization complex type + * @param Z the serialization primitive type + **/ + private class DataLoader( + val key: NamespacedKey, + val dataType: PersistentDataType, + val fieldDataClass: Class, + val defaultValue: Z?, + val complexTransform: (Z?) -> J + ) { + fun get(container: PersistentDataContainer): J { + val raw = container.get(key, dataType) ?: defaultValue ?: throw SerializationException() + + return complexTransform(raw) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt index 7346e9aca2..d96458d459 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt @@ -27,11 +27,6 @@ class SpongeNode() : MultiNode { return true } - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - } - override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt index 6c6cae92f7..6a8e16c121 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -2,17 +2,19 @@ package net.horizonsend.ion.server.features.transport.node.nodes import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import kotlin.reflect.KClass /** - * Represents a single node, or step, in a transport transportNetwork + * Represents a single node, or step, in transport transportNetwork **/ interface TransportNode : PDCSerializable { - override val type: Companion get() = Companion + override val serializationType: Companion get() = Companion /** * The neighboring nodes that this node may transport to @@ -29,11 +31,6 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java @@ -42,21 +39,24 @@ interface TransportNode : PDCSerializable(val field: KClass, val data: T) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 46df77b9dc..c79bea50c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -96,6 +96,7 @@ object NamespacedKeys { val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") val NODE_COVERED_POSITIONS = key("node_covered_positions") val NODE_TYPE = key("node_type") + val NODE_DATA = key("node_data") val NODES = key("chunk_power_nodes") val NODE_LOCATIONS = key("chunk_power_node_locations") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt index ff7b51179c..83e9f8a7d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt @@ -6,13 +6,13 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType interface PDCSerializable > { - val type: T + val serializationType: T fun serialize(adapterContext: PersistentDataAdapterContext, data: V): PersistentDataContainer { - return type.toPrimitive(data, adapterContext) + return serializationType.toPrimitive(data, adapterContext) } fun store(destination: PersistentDataContainer, key: NamespacedKey, data: V) { - destination.set(key, type, data) + destination.set(key, serializationType, data) } } From dd3ced574c0d65fdb6ec780686e2f4dcdfc6b6c5 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 30 Apr 2024 13:29:24 -0500 Subject: [PATCH 029/500] rebuild nodes util --- .../server/command/admin/IonChunkCommand.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 4bf82f723f..2a305cf751 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,10 +4,15 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.world.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text @@ -73,4 +78,24 @@ object IonChunkCommand : SLCommand() { sender.highlightBlock(vec, 50L) } } + + @Subcommand("rebuild nodes") + @CommandCompletion("power") /* |item|gas") */ + fun rebuildNodes(sender: Player, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { + val ionChunk = sender.chunk.ion() + + val grid = when (network) { + "power" -> ionChunk.transportNetwork.powerNetwork +// "item" -> ionChunk.transportNetwork.pipeGrid +// "gas" -> ionChunk.transportNetwork.gasGrid + else -> return@launch fail { "invalid network" } + } + + for (x in 0..15) for (y in ionChunk.world.minHeight..ionChunk.world.maxHeight) for (z in 0..15) { + val realX = x + ionChunk.originX + val realZ = z + ionChunk.originZ + + grid.createNodeFromBlock(getBlockSnapshotAsync(sender.world, realX, y, realZ)!!) + } + } } From 4dd3b6e357f6f72cc960d05807c2358eab4f62bc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 30 Apr 2024 13:29:36 -0500 Subject: [PATCH 030/500] Revert "better(ish) deserialization" This reverts commit 1e9e69d350683fb0b9e882c62653ff802aa793e6. --- .../multiblock/entity/MultiblockEntity.kt | 2 +- .../features/transport/node/NodeType.kt | 81 ++----------------- .../transport/node/nodes/SpongeNode.kt | 5 ++ .../transport/node/nodes/TransportNode.kt | 24 +++--- .../persistence/NamespacedKeys.kt | 1 - .../persistence/PDCSerializable.kt | 6 +- 6 files changed, 29 insertions(+), 90 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 3ef430bb9f..0cdab7c432 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -32,7 +32,7 @@ abstract class MultiblockEntity( var world: World, var signDirection: BlockFace ): PDCSerializable { - override val serializationType: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion + override val type: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion /** * Returns the origin of this multiblock as a Location diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 5f9f918acc..b3f4aaf888 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,91 +1,26 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.node.nodes.SpongeNode import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.NamespacedKey -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import kotlin.reflect.KClass -import kotlin.reflect.KProperty -enum class NodeType(val javaClass: Class, val kotlinClass: KClass, registerDataLoaders: NodeType.() -> Unit = {}) { - // GENERAL - //TODO Extractor - //TODO Straight node for power and gas - //TODO Merge node +enum class NodeType(val clazz: Class) { + //POWER + SPONGE_NODE(SpongeNode::class.java), - // POWER - SPONGE_NODE(SpongeNode::class.java, SpongeNode::class, { - addDataLoader(SpongeNode::positions, NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, MutableSet::class.java) { LongOpenHashSet(it) } - }), - //TODO Power flow meter - //TODO Power input - //TODO Power Splitter + //GAS - // GAS - //TODO pane node - - // ITEM - //TODO Sponge equivalent for glass color + //ITEM ; - private val dataLoaders: MutableMap, DataLoader<*, *, *>> = mutableMapOf() - - fun addDataLoader( - property: KProperty, - storageKey: NamespacedKey, - dataType: PersistentDataType, - fieldDataClass: Class, - defaultValue: Z? = null, - complexTransform: (Z?) -> J - ) { - dataLoaders[property] = DataLoader(storageKey, dataType, fieldDataClass, defaultValue, complexTransform) - } - - fun load(additionalData: PersistentDataContainer): TransportNode { - val fields: Array> = dataLoaders.map { it.value.fieldDataClass }.toTypedArray() - val data: Array = dataLoaders.map { (_, loader) -> loader.get(additionalData) }.toTypedArray() - - return javaClass.getDeclaredConstructor(*fields).newInstance(data) - } - - init { - registerDataLoaders(this) + fun newInstance(): TransportNode { + return clazz.getDeclaredConstructor().newInstance() } companion object { val type = EnumDataType(NodeType::class.java) - private val byNode: Map, NodeType> = entries.associateBy { it.javaClass } + private val byNode: Map, NodeType> = entries.associateBy { it.clazz } operator fun get(node: TransportNode): NodeType = byNode[node.javaClass] ?: throw NoSuchElementException("Unregistered node type ${node.javaClass.simpleName}!") } - - /** - * @param key The key that the data will be stored in - * @param dataType The persistent data type of the type - * @param fieldDataClass The Java class of the type of the field - * @param defaultValue The default value if none is found from serialization. If not provided, and no data is found, a serialization exception will occur - * @param complexTransform The transform applied to the value retrieved from the persistent data container - * - * @param J the final type - * @param T the serialization complex type - * @param Z the serialization primitive type - **/ - private class DataLoader( - val key: NamespacedKey, - val dataType: PersistentDataType, - val fieldDataClass: Class, - val defaultValue: Z?, - val complexTransform: (Z?) -> J - ) { - fun get(container: PersistentDataContainer): J { - val raw = container.get(key, dataType) ?: defaultValue ?: throw SerializationException() - - return complexTransform(raw) - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt index d96458d459..7346e9aca2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt @@ -27,6 +27,11 @@ class SpongeNode() : MultiNode { return true } + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } + } + override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt index 6a8e16c121..6c6cae92f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -2,19 +2,17 @@ package net.horizonsend.ion.server.features.transport.node.nodes import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import kotlin.reflect.KClass /** - * Represents a single node, or step, in transport transportNetwork + * Represents a single node, or step, in a transport transportNetwork **/ interface TransportNode : PDCSerializable { - override val serializationType: Companion get() = Companion + override val type: Companion get() = Companion /** * The neighboring nodes that this node may transport to @@ -31,6 +29,11 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java @@ -39,24 +42,21 @@ interface TransportNode : PDCSerializable(val field: KClass, val data: T) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index c79bea50c2..46df77b9dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -96,7 +96,6 @@ object NamespacedKeys { val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") val NODE_COVERED_POSITIONS = key("node_covered_positions") val NODE_TYPE = key("node_type") - val NODE_DATA = key("node_data") val NODES = key("chunk_power_nodes") val NODE_LOCATIONS = key("chunk_power_node_locations") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt index 83e9f8a7d4..ff7b51179c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt @@ -6,13 +6,13 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType interface PDCSerializable > { - val serializationType: T + val type: T fun serialize(adapterContext: PersistentDataAdapterContext, data: V): PersistentDataContainer { - return serializationType.toPrimitive(data, adapterContext) + return type.toPrimitive(data, adapterContext) } fun store(destination: PersistentDataContainer, key: NamespacedKey, data: V) { - destination.set(key, serializationType, data) + destination.set(key, type, data) } } From 270bfb3f57fa6d8d4a212443411ae862a231ee7f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 30 Apr 2024 14:23:03 -0500 Subject: [PATCH 031/500] Reduce data duplication, simplification --- .../transport/grid/ChunkPowerNetwork.kt | 2 +- ...ortNetwork.kt => ChunkTransportNetwork.kt} | 33 +++++-------------- .../features/transport/node/ExtractorNode.kt | 4 +-- .../features/transport/node/GridNode.kt | 4 +-- .../transport/node/general/GateNode.kt | 4 +-- .../transport/node/general/JunctionNode.kt | 4 +-- .../transport/node/general/LinearNode.kt | 6 ++-- .../transport/node/nodes/SpongeNode.kt | 1 + .../transport/node/nodes/TransportNode.kt | 8 ++++- .../node/nodes/{ => type}/MultiNode.kt | 11 ++++++- .../transport/node/nodes/type/SingleNode.kt | 15 +++++++++ .../transport/node/power/MergeNode.kt | 4 +-- .../node/power/PowerExtractorNode.kt | 4 +-- .../transport/node/power/PowerFlowMeter.kt | 4 +-- .../transport/node/power/SplitterNode.kt | 4 +-- .../server/features/transport/step/Step.kt | 4 +-- .../persistence/NamespacedKeys.kt | 1 - 17 files changed, 64 insertions(+), 49 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/{TransportNetwork.kt => ChunkTransportNetwork.kt} (80%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/{ => type}/MultiNode.kt (72%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index e98e81c555..6fd8f2c3d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -26,7 +26,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap -class ChunkPowerNetwork(manager: ChunkTransportManager) : TransportNetwork(manager) { +class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { val poweredMultiblockEntities = ConcurrentHashMap() val extractors = ConcurrentHashMap() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt similarity index 80% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index 374e843f53..792f2bc845 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/TransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.grid -import com.manya.pdc.base.MapDataType import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch @@ -10,17 +9,16 @@ import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.Consolidatable import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_LOCATIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.seconds import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import java.util.concurrent.ConcurrentHashMap -import java.util.stream.Collectors -abstract class TransportNetwork(val manager: ChunkTransportManager) { +abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val nodes: ConcurrentHashMap = ConcurrentHashMap() val world get() = manager.chunk.world @@ -28,7 +26,7 @@ abstract class TransportNetwork(val manager: ChunkTransportManager) { protected abstract val namespacedKey: NamespacedKey -// val grids: Nothing = TODO("TransportNetwork system") +// val grids: Nothing = TODO("ChunkTransportNetwork system") init { loadData() @@ -46,39 +44,26 @@ abstract class TransportNetwork(val manager: ChunkTransportManager) { abstract fun processBlockRemoval(key: Long) abstract fun processBlockAddition(key: Long, new: BlockSnapshot) - companion object { - private val locationDataType = MapDataType( - Collectors.toMap({ it.key }, { it.value }), - PersistentDataType.LONG, - PersistentDataType.INTEGER - ) - } - /** * Load stored node data from the chunk **/ private fun loadData() { val existing = pdc.get(POWER_TRANSPORT, PersistentDataType.TAG_CONTAINER) ?: return - val nodeLocations = existing.get(NODE_LOCATIONS, locationDataType)!! + // Deserialize once val nodeData = existing.get(NODES, PersistentDataType.TAG_CONTAINER_ARRAY)!!.map { TransportNode.fromPrimitive(it, pdc.adapterContext) } - - for ((locationKey, nodeIndex) in nodeLocations) { - nodes[locationKey] = nodeData[nodeIndex] - } + nodeData.forEach { it.handlePlacement(this) } } fun save(adapterContext: PersistentDataAdapterContext) { val container = adapterContext.newPersistentDataContainer() - val serializedNodes = nodes.values.associateWith { nodes.values.indexOf(it) to it.serialize(adapterContext, it) } - //TODO find better implementation of storage + val serializedNodes: MutableMap> = mutableMapOf() - val dataMap = nodes.map { (key, node) -> - key to serializedNodes[node]!!.first - }.toMap() + nodes.forEach { (_, node) -> + serializedNodes[node] = nodes.values.indexOf(node) to node.serialize(adapterContext, node) + } - container.set(NODE_LOCATIONS, locationDataType, dataMap) container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.seconds().toTypedArray()) pdc.set(namespacedKey, PersistentDataType.TAG_CONTAINER, container) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt index bc125123f6..a24822724b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap abstract class ExtractorNode( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt index bfd682ec40..331f951710 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -8,7 +8,7 @@ import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap interface GridNode { - val parentTransportNetwork: TransportNetwork + val parentTransportNetwork: ChunkTransportNetwork val x: Int val y: Int val z: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt index ecdd8e92bf..6149382fce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt @@ -1,13 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.general -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class GateNode( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 694eced762..e95d2fab4c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.general -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step @@ -14,7 +14,7 @@ import kotlin.random.asKotlinRandom * An omnidirectional node **/ class JunctionNode( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index 15273bbc91..055e2db6fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.general import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.Consolidatable import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step @@ -15,7 +15,7 @@ import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap class LinearNode( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, @@ -23,7 +23,7 @@ class LinearNode( val occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) ) : GridNode, Consolidatable { constructor( - transportNetwork: TransportNetwork, + transportNetwork: ChunkTransportNetwork, x: Int, y: Int, z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt index 7346e9aca2..3031bab6cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.nodes import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.nodes.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ALL_DIRECTIONS import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt index 6c6cae92f7..da6cf801ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.nodes import kotlinx.serialization.SerializationException +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable @@ -9,7 +10,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType /** - * Represents a single node, or step, in a transport transportNetwork + * Represents a single node, or step, in transport transportNetwork **/ interface TransportNode : PDCSerializable { override val type: Companion get() = Companion @@ -34,6 +35,11 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt similarity index 72% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt index 0624ea5be6..ac64710b3d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt @@ -1,4 +1,7 @@ -package net.horizonsend.ion.server.features.transport.node.nodes +package net.horizonsend.ion.server.features.transport.node.nodes.type + +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode /** * A transport node that may cover many blocks to avoid making unnecessary steps @@ -25,4 +28,10 @@ interface MultiNode : TransportNode { nodes[position] = new } } + + override fun handlePlacement(network: ChunkTransportNetwork) { + for (key in positions) { + network.nodes[key] = this + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt new file mode 100644 index 0000000000..71223f0796 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.transport.node.nodes.type + +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode + +/** + * A node that only occupies a single block + **/ +interface SingleNode : TransportNode { + val position: Long + + override fun handlePlacement(network: ChunkTransportNetwork) { + network.nodes[position] = this + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt index ff580c5ae9..080d2eb18e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step @@ -8,7 +8,7 @@ import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class MergeNode( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index b9ec2f2966..c33fadbc29 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.container.ResourceContainer import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.ExtractorNode import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.PowerStep @@ -70,7 +70,7 @@ class PowerExtractorNode( } companion object { - fun isSolarPanel(parentTransportNetwork: TransportNetwork, x: Int, y: Int, z: Int): Boolean = runBlocking { + fun isSolarPanel(parentTransportNetwork: ChunkTransportNetwork, x: Int, y: Int, z: Int): Boolean = runBlocking { val aboveOne = getBlockSnapshotAsync(parentTransportNetwork.world, x, y + 1, z, false) val aboveTwo = getBlockSnapshotAsync(parentTransportNetwork.world, x, y + 2, z, false) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 2a9b165ad1..34bf81151a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -1,14 +1,14 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class PowerFlowMeter( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt index 774b3a2b51..dce19cbd7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt @@ -1,13 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.features.transport.step.Step import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class SplitterNode( - override val parentTransportNetwork: TransportNetwork, + override val parentTransportNetwork: ChunkTransportNetwork, override val x: Int, override val y: Int, override val z: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index 756622a0d4..f3bbb9b716 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -2,14 +2,14 @@ package net.horizonsend.ion.server.features.transport.step import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.GridNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.block.BlockFace abstract class Step( - open val transportNetwork: TransportNetwork, + open val transportNetwork: ChunkTransportNetwork, open val origin: ResourceContainer<*>?, var direction: BlockFace, var currentNode: GridNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 46df77b9dc..e219b69591 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -98,7 +98,6 @@ object NamespacedKeys { val NODE_TYPE = key("node_type") val NODES = key("chunk_power_nodes") - val NODE_LOCATIONS = key("chunk_power_node_locations") fun key(key: String) = NamespacedKey(IonServer, key) From ecbec18c6dfdb7fc4fa05695f80a2051e1e3d0e7 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 1 May 2024 01:38:09 -0500 Subject: [PATCH 032/500] node splitting --- .../transport/grid/ChunkPowerNetwork.kt | 19 +++++++---------- .../transport/node/nodes/SpongeNode.kt | 20 ------------------ .../transport/node/nodes/TransportNode.kt | 9 +++++++- .../transport/node/nodes/type/MultiNode.kt | 21 +++++++++++++++---- 4 files changed, 32 insertions(+), 37 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index 6fd8f2c3d2..fabc399a07 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -71,14 +71,11 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - override fun processBlockRemoval(key: Long) { - manager.scope.launch { - val previousNode = nodes[key] + override fun processBlockRemoval(key: Long) { manager.scope.launch { + val previousNode = nodes[key] ?: return@launch - nodes.remove(key) - //TODO check for splits - } - } + previousNode.handleRemoval(this@ChunkPowerNetwork, key) + }} override fun processBlockAddition(key: Long, new: BlockSnapshot) { createNodeFromBlock(new) @@ -90,13 +87,11 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } val tickExecutor = IntervalExecutor(20) { - for ((key, extractor) in extractors.filterValues { it.transferableNeighbors.isNotEmpty() }) { - extractor.startStep().step() - } + } override fun tick() { - tickExecutor() +// tickExecutor() } private fun collectPowerMultiblockEntities() { @@ -107,7 +102,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - private fun addSpongeNode(position: Long) { + fun addSpongeNode(position: Long) { val neighbors = getNeighborNodes(position, nodes) when (neighbors.size) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt index 3031bab6cc..ce0180e319 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt @@ -2,11 +2,8 @@ package net.horizonsend.ion.server.features.transport.node.nodes import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.nodes.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS -import net.horizonsend.ion.server.miscellaneous.utils.ALL_DIRECTIONS -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -36,21 +33,4 @@ class SpongeNode() : MultiNode { override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } - - override fun shouldSplit(position: Long, nodes: MutableMap): Boolean { - // If it covers a single or two blocks it cannot be split, simply remove it - if (positions.size < 2) return false - - // Get neighbors by blockface relation - val neighborPositions: Map = getNeighborNodes(position, nodes) - - // If covered removing this node results in an equal number of neighbors and positions then none are touching - if (neighborPositions.size == (positions.size - 1)) return true - - // All 26 adjacent directions - val adjacentNeighborPositions = getNeighborNodes(position, positions, ALL_DIRECTIONS) - -// if (adjacentNeighborPositions) - return false - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt index da6cf801ab..f2c26ea606 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt @@ -38,7 +38,14 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt index ac64710b3d..2f2db99e5a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.nodes.type +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode @@ -12,10 +13,22 @@ interface MultiNode : TransportNode { **/ val positions: MutableSet - /** - * Returns whether the removal of the provided position should result in the splitting of a combined node - **/ - fun shouldSplit(position: Long, nodes: MutableMap): Boolean + override fun handleRemoval(network: ChunkTransportNetwork, position: Long) { + network as ChunkPowerNetwork + + network.nodes.remove(position) + positions.remove(position) + + // Remove all + positions.forEach { + network.nodes.remove(it) + } + + // Create new nodes, automatically merging together + positions.forEach { + network.addSpongeNode(it) + } + } /** * Drain all the positions and connections to the provided node From 0a88f7781ba1a3f9210c77dbe5614b688f72fa37 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 1 May 2024 02:45:11 -0500 Subject: [PATCH 033/500] delete old stuff, end rod node --- .../transport/grid/ChunkPowerNetwork.kt | 90 +++++++++++++------ .../transport/grid/ChunkTransportNetwork.kt | 4 +- .../features/transport/node/NodeType.kt | 4 +- .../features/transport/node/NodeUtils.kt | 6 +- .../transport/node/general/GateNode.kt | 24 ----- .../transport/node/general/JunctionNode.kt | 45 ---------- .../transport/node/general/LinearNode.kt | 57 ------------ .../transport/node/power/EndRodNode.kt | 31 +++++++ .../transport/node/power/GrabbyNode.kt | 4 - .../transport/node/power/MergeNode.kt | 25 ------ .../node/power/PowerExtractorNode.kt | 80 ----------------- .../transport/node/power/PowerFlowMeter.kt | 29 ------ .../transport/node/power/PowerInputNode.kt | 69 -------------- .../transport/node/power/PowerNodes.kt | 10 --- .../transport/node/power/SplitterNode.kt | 24 ----- .../node/{nodes => power}/SpongeNode.kt | 4 +- .../node/{nodes => power}/TransportNode.kt | 2 +- .../node/{nodes => }/type/MultiNode.kt | 4 +- .../node/{nodes => }/type/SingleNode.kt | 4 +- .../utils/coordinates/NewBlockKey.kt | 7 ++ 20 files changed, 117 insertions(+), 406 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{nodes => power}/SpongeNode.kt (90%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{nodes => power}/TransportNode.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{nodes => }/type/MultiNode.kt (89%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{nodes => }/type/SingleNode.kt (69%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index fabc399a07..6cae412c67 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -1,23 +1,19 @@ package net.horizonsend.ion.server.features.transport.grid import kotlinx.coroutines.launch -import net.horizonsend.ion.server.features.customblocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.general.GateNode -import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes -import net.horizonsend.ion.server.features.transport.node.nodes.SpongeNode -import net.horizonsend.ion.server.features.transport.node.power.MergeNode -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.power.SplitterNode +import net.horizonsend.ion.server.features.transport.node.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor +import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp +import net.horizonsend.ion.server.miscellaneous.utils.faces import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull import org.bukkit.Material @@ -28,7 +24,7 @@ import java.util.concurrent.ConcurrentHashMap class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { val poweredMultiblockEntities = ConcurrentHashMap() - val extractors = ConcurrentHashMap() +// val extractors = ConcurrentHashMap() override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT @@ -36,7 +32,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( collectPowerMultiblockEntities() } - override fun createNodeFromBlock(block: BlockSnapshot) { + override suspend fun createNodeFromBlock(block: BlockSnapshot) { + println("Triggering event") val x = block.x val y = block.y val z = block.z @@ -45,29 +42,29 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( when { // Extract power from storage - block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } +// block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } // Add power to storage - block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) +// block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) // Straight wires - block.type == Material.END_ROD -> LinearNode(this, x, y, z, block.data as Directional) + block.type == Material.END_ROD -> addEndRodNode(block.data as Directional, key) // Omnidirectional wires block.type == Material.SPONGE -> addSpongeNode(key) // Merge node behavior - block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) - block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) +// block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) +// block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) // Split power evenly - block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) +// block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) // Redstone controlled gate - block.type.isRedstoneLamp -> GateNode(this, x, y, z) +// block.type.isRedstoneLamp -> GateNode(this, x, y, z) // Power flow meter - block.type == Material.OBSERVER -> PowerFlowMeter(this, x, y, z) +// block.type == Material.OBSERVER -> PowerFlowMeter(this, x, y, z) } } @@ -77,10 +74,9 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( previousNode.handleRemoval(this@ChunkPowerNetwork, key) }} - override fun processBlockAddition(key: Long, new: BlockSnapshot) { + override fun processBlockAddition(key: Long, new: BlockSnapshot) { manager.scope.launch { createNodeFromBlock(new) - //TODO - } + }} fun removeNode(key: Long) { nodes.remove(key) @@ -103,7 +99,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } fun addSpongeNode(position: Long) { - val neighbors = getNeighborNodes(position, nodes) + val neighbors = getNeighborNodes(position, nodes).filter { it.value is SpongeNode } when (neighbors.size) { // New sponge node @@ -121,7 +117,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( in 2..6 -> { // Get the larger val spongeNeighbors: MutableMap = mutableMapOf() - neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } + neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } // Get the largest neighbor val largestNeighbor = spongeNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: return @@ -137,4 +133,48 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } } + + suspend fun addEndRodNode(data: Directional, position: Long) { + val axis = data.facing.axis + + // The neighbors in the direction of the wire's facing, that are also facing that direction + val neighbors = getNeighborNodes(position, nodes, axis.faces.toList()).filterKeys { + val relative = getRelative(position, it) + (getBlockSnapshotAsync(world, relative, false)?.data as? Directional)?.facing?.axis == axis + }.filter { it.value is EndRodNode } + + when (neighbors.size) { + // Disconnected + 0 -> nodes[position] = EndRodNode(position) + + 1 -> { + val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") + if (neighbor !is EndRodNode) return + + neighbor.positions += position + nodes[position] = neighbor + } + + // Should be a max of 2 + 2 -> { + // Get the larger + val wireNeighbors: MutableMap = mutableMapOf() + neighbors.mapNotNullTo(wireNeighbors) { (key, value) -> (value as? EndRodNode)?.let { key to value } } + + // Get the largest neighbor + val largestNeighbor = wireNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: return + + // Merge all other connected nodes into the largest + wireNeighbors.forEach { + it.value.drainTo(largestNeighbor, this.nodes) + } + + // Add this node + largestNeighbor.positions.add(position) + nodes[position] = largestNeighbor + } + + else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index 792f2bc845..88010aa149 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.Consolidatable -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -39,7 +39,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { * * Inheritors may choose to save persistent data, or not **/ - abstract fun createNodeFromBlock(block: BlockSnapshot) + abstract suspend fun createNodeFromBlock(block: BlockSnapshot) abstract fun processBlockRemoval(key: Long) abstract fun processBlockAddition(key: Long, new: BlockSnapshot) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index b3f4aaf888..1aa7811c12 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.node.nodes.SpongeNode -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.features.transport.node.power.TransportNode enum class NodeType(val clazz: Class) { //POWER diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index 1a5075f27c..a40b9c8943 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.BlockFace -fun getNeighborNodes(position: Long, nodes: Map, checkFaces: Set = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { +fun getNeighborNodes(position: Long, nodes: Map, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { val x = getX(position) val y = getY(position) val z = getZ(position) @@ -17,7 +17,7 @@ fun getNeighborNodes(position: Long, nodes: Map, checkFaces nodes[toBlockKey(x + it.modX, y + it.modY, z + it.modZ)] } -fun getNeighborNodes(position: Long, nodes: Collection, checkFaces: Set = ADJACENT_BLOCK_FACES) = checkFaces.mapNotNull { +fun getNeighborNodes(position: Long, nodes: Collection, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.mapNotNull { val x = getX(position) val y = getY(position) val z = getZ(position) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt deleted file mode 100644 index 6149382fce..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/GateNode.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.general - -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -class GateNode( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - return true - } - - override fun processStep(step: Step) { - TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt deleted file mode 100644 index e95d2fab4c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.general - -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.ExtractorNode -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.TransferStatus -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ThreadLocalRandom -import kotlin.random.asKotlinRandom - -/** - * An omnidirectional node - **/ -class JunctionNode( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - return node !is ExtractorNode<*> - } - - override fun processStep(step: Step) { - val neighbor = transferableNeighbors - .entries - .filter { it.key != step.direction } - .randomOrNull(ThreadLocalRandom.current().asKotlinRandom()) - - if (neighbor == null) { - step.status = TransferStatus.BLOCKED - - return - } - - val (offset, node) = neighbor - - step.direction = offset - step.currentNode = node - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt deleted file mode 100644 index 055e2db6fc..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ /dev/null @@ -1,57 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.general - -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.Consolidatable -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.faces -import net.horizonsend.ion.server.miscellaneous.utils.iterator -import org.bukkit.Axis -import org.bukkit.block.BlockFace -import org.bukkit.block.data.Directional -import java.util.concurrent.ConcurrentHashMap - -class LinearNode( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, - val axis: Axis, - val occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) -) : GridNode, Consolidatable { - constructor( - transportNetwork: ChunkTransportNetwork, - x: Int, - y: Int, - z: Int, - data: Directional, - occupiedPositions: LongOpenHashSet = LongOpenHashSet.of(toBlockKey(x, y, z)) - ) : this(transportNetwork, x, y, z, data.facing.axis, occupiedPositions) - - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - // Only allow transfer to wires along the same axis - return offset.axis == axis - } - - override fun processStep(step: Step) { - TODO("Not yet implemented") - } - - override fun consolidate() { - for (face in this.axis.faces) { - val node = getNeighbor(face) ?: continue - if (node !is LinearNode) continue - - // Eat the neighbor - occupiedPositions.addAll(node.occupiedPositions) - - // Replace the neighbor with this - node.replace(this) - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt new file mode 100644 index 0000000000..22051d191e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -0,0 +1,31 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +class EndRodNode() : MultiNode { + constructor(origin: Long) : this() { + positions.add(origin) + } + + override val positions: MutableSet = LongOpenHashSet() + + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + + override fun isTransferable(position: Long, node: TransportNode): Boolean { + return true + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt deleted file mode 100644 index 80e0fb782e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/GrabbyNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -class GrabbyNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt deleted file mode 100644 index 080d2eb18e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.ExtractorNode -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -class MergeNode( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - return node !is ExtractorNode<*> - } - - override fun processStep(step: Step) { - TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt deleted file mode 100644 index c33fadbc29..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ /dev/null @@ -1,80 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.ExtractorNode -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.PowerStep -import net.horizonsend.ion.server.features.transport.step.Step -import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.World -import org.bukkit.block.BlockFace - -class PowerExtractorNode( - override val parentTransportNetwork: ChunkPowerNetwork, - x: Int, - y: Int, - z: Int, - val solarPanel: Boolean = isSolarPanel(parentTransportNetwork, x, y, z) -) : ExtractorNode(parentTransportNetwork, x, y, z) { - var lastTicked: Long = System.currentTimeMillis() - - override fun getExtractableInventories(): Collection> { - TODO("Not yet implemented") - } - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - // Don't send power to other extractors - if (node is PowerExtractorNode) return false - - // Power may only exit from an input - if (node is PowerInputNode) return false - - // All others allowed - return true - } - - fun tickSolarPanel(): Int { - val time = System.currentTimeMillis() - val deltaMs = time - lastTicked - - val deltaSeconds = deltaMs / 1000.0 - return getPower(deltaSeconds) - } - - private fun getPower(delta: Double): Int { - val environment = parentTransportNetwork.world.environment - - val power = 5.0 / if (environment == World.Environment.NORMAL) 1.0 else 2.0 - - return (power * delta).toInt() - } - - override fun processStep(step: Step) { - println("Stepping extractor") - } - - fun startStep(): Step { - val direction = transferableNeighbors.keys().toList().random() - - return PowerStep( - transportNetwork = parentTransportNetwork, - origin = null, - direction = direction, - this - ) - } - - companion object { - fun isSolarPanel(parentTransportNetwork: ChunkTransportNetwork, x: Int, y: Int, z: Int): Boolean = runBlocking { - val aboveOne = getBlockSnapshotAsync(parentTransportNetwork.world, x, y + 1, z, false) - val aboveTwo = getBlockSnapshotAsync(parentTransportNetwork.world, x, y + 2, z, false) - - return@runBlocking aboveOne?.type == Material.DIAMOND_BLOCK && aboveTwo?.type == Material.DAYLIGHT_DETECTOR - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt deleted file mode 100644 index 34bf81151a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ /dev/null @@ -1,29 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -class PowerFlowMeter( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode, PowerNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - return true - } - - override fun processStep(step: Step) { - TODO("Not yet implemented") - } - - override val multiblocks: MutableList - get() = TODO("Not yet implemented") -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt deleted file mode 100644 index f908e21faf..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ /dev/null @@ -1,69 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.TransferStatus -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -class PowerInputNode( - override val parentTransportNetwork: ChunkPowerNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode, PowerNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - override val multiblocks: MutableList = getNeighboringMultiblocks() - - /** - * Gets the multiblocks to which this can input power - **/ - fun getNeighboringMultiblocks(): MutableList { - val multiblocks = mutableListOf() - - for ((offsetX, offsetY, offsetZ) in offsets) { - val x = this.x + offsetX - val y = this.y + offsetY - val z = this.z + offsetZ - - val key = toBlockKey(x, y, z) - - val multi = parentTransportNetwork.poweredMultiblockEntities[key] ?: continue - - multiblocks.add(multi) - } - - return multiblocks - } - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - // May only accept power - return false - } - - companion object { - /** - * The offsets at which a multiblock sign might be found. - **/ - private val offsets = setOf( - // most multiblocks have the sign a block up and out of the computer - Vec3i(1, 1, 0), Vec3i(-1, 1, 0), Vec3i(0, 1, -1), Vec3i(0, 1, 1), - // power cells have it on the block - Vec3i(1, 0, 0), Vec3i(-1, 0, 0), Vec3i(0, 0, -1), Vec3i(0, 0, 1), - // drills have it on a corner - Vec3i(-1, 0, -1), Vec3i(1, 0, -1), Vec3i(1, 0, 1), Vec3i(-1, 0, 1), - // upside down mining lasers have signs below - Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), - ) - } - - override fun processStep(step: Step) { - step.currentNode = this - step.status = TransferStatus.COMPLETE -// TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt deleted file mode 100644 index 86973c5c81..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodes.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity - -/** - * - **/ -interface PowerNode { - val multiblocks: MutableList -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt deleted file mode 100644 index dce19cbd7a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SplitterNode.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.power - -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.features.transport.step.Step -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -class SplitterNode( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - override fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean { - return true - } - - override fun processStep(step: Step) { - TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index ce0180e319..51166b029f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.nodes +package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.node.nodes.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt index f2c26ea606..81220376fb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.nodes +package net.horizonsend.ion.server.features.transport.node.power import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt similarity index 89% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 2f2db99e5a..9a0ec2e5f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.nodes.type +package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.TransportNode /** * A transport node that may cover many blocks to avoid making unnecessary steps diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 71223f0796..f2005930d1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/nodes/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.transport.node.nodes.type +package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.nodes.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.TransportNode /** * A node that only occupies a single block diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt index 1654f502a3..904ea19756 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.miscellaneous.utils.coordinates import net.minecraft.core.BlockPos +import org.bukkit.block.BlockFace /** * Packs a x, y, z coordinate into a long @@ -12,3 +13,9 @@ fun toVec3i(key: Long): Vec3i = Vec3i(getX(key), getY(key), getZ(key)) fun getX(key: Long) : Int = BlockPos.getX(key) fun getY(key: Long) : Int = BlockPos.getY(key) fun getZ(key: Long) : Int = BlockPos.getZ(key) + +fun getRelative(key: Long, direction: BlockFace, distance: Int = 1): Long = toBlockKey( + getX(key) + (direction.modX * distance), + getY(key) + (direction.modY * distance), + getZ(key) + (direction.modZ * distance) +) From d2f582b6408fd341202106168a555f886f5efa4b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 3 May 2024 01:28:23 -0500 Subject: [PATCH 034/500] Move node creation to separate factory file, fix end rod splitting --- .../transport/ChunkTransportManager.kt | 9 +- .../transport/grid/ChunkPowerNetwork.kt | 132 +----------------- .../transport/grid/ChunkTransportNetwork.kt | 10 +- .../features/transport/node/NodeFactory.kt | 10 ++ .../transport/node/power/EndRodNode.kt | 14 ++ .../transport/node/power/PowerNodeFactory.kt | 131 +++++++++++++++++ .../transport/node/power/SpongeNode.kt | 17 ++- .../transport/node/power/TransportNode.kt | 2 +- .../features/transport/node/type/MultiNode.kt | 14 +- .../server/miscellaneous/utils/Collections.kt | 21 ++- .../utils/coordinates/Coordinates.kt | 17 ++- .../utils/coordinates/NewBlockKey.kt | 42 ++++-- .../miscellaneous/utils/coordinates/Vec3i.kt | 4 +- 13 files changed, 252 insertions(+), 171 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 112c23c21a..416b3f216e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Compani import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Chunk import org.bukkit.event.block.BlockBreakEvent @@ -33,10 +34,12 @@ class ChunkTransportManager( // gasGrid.setup() } + val tickExecutor = IntervalExecutor(40) { scope.launch { + + }} + fun tick() { - scope.launch { powerNetwork.tick() } -// scope.launch { pipeGrid.tick() } -// scope.launch { gasGrid.tick() } + tickExecutor() } fun save() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index 6cae412c67..442f419eeb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -3,23 +3,12 @@ package net.horizonsend.ion.server.features.transport.grid import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.getNeighborNodes -import net.horizonsend.ion.server.features.transport.node.power.EndRodNode -import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.features.transport.node.NodeFactory +import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.faces -import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo -import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull -import org.bukkit.Material import org.bukkit.NamespacedKey -import org.bukkit.block.BlockFace -import org.bukkit.block.data.Directional import java.util.concurrent.ConcurrentHashMap class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { @@ -27,47 +16,12 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( // val extractors = ConcurrentHashMap() override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT + override val nodeFactory: NodeFactory<*> = PowerNodeFactory override fun setup() { collectPowerMultiblockEntities() } - override suspend fun createNodeFromBlock(block: BlockSnapshot) { - println("Triggering event") - val x = block.x - val y = block.y - val z = block.z - - val key = toBlockKey(x, y, z) - - when { - // Extract power from storage -// block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } - - // Add power to storage -// block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) - - // Straight wires - block.type == Material.END_ROD -> addEndRodNode(block.data as Directional, key) - - // Omnidirectional wires - block.type == Material.SPONGE -> addSpongeNode(key) - - // Merge node behavior -// block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) -// block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) - - // Split power evenly -// block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) - - // Redstone controlled gate -// block.type.isRedstoneLamp -> GateNode(this, x, y, z) - - // Power flow meter -// block.type == Material.OBSERVER -> PowerFlowMeter(this, x, y, z) - } - } - override fun processBlockRemoval(key: Long) { manager.scope.launch { val previousNode = nodes[key] ?: return@launch @@ -97,84 +51,4 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( poweredMultiblockEntities[key] = entity } } - - fun addSpongeNode(position: Long) { - val neighbors = getNeighborNodes(position, nodes).filter { it.value is SpongeNode } - - when (neighbors.size) { - // New sponge node - 0 -> nodes[position] = SpongeNode(position) - // Consolidate into neighbor - 1 -> { - val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - if (neighbor !is SpongeNode) return - - neighbor.positions += position - nodes[position] = neighbor - } - - // Join multiple neighbors together - in 2..6 -> { - // Get the larger - val spongeNeighbors: MutableMap = mutableMapOf() - neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } - - // Get the largest neighbor - val largestNeighbor = spongeNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: return - - // Merge all other connected nodes into the largest - spongeNeighbors.forEach { - it.value.drainTo(largestNeighbor, this.nodes) - } - - // Add this node - largestNeighbor.positions.add(position) - nodes[position] = largestNeighbor - } - } - } - - suspend fun addEndRodNode(data: Directional, position: Long) { - val axis = data.facing.axis - - // The neighbors in the direction of the wire's facing, that are also facing that direction - val neighbors = getNeighborNodes(position, nodes, axis.faces.toList()).filterKeys { - val relative = getRelative(position, it) - (getBlockSnapshotAsync(world, relative, false)?.data as? Directional)?.facing?.axis == axis - }.filter { it.value is EndRodNode } - - when (neighbors.size) { - // Disconnected - 0 -> nodes[position] = EndRodNode(position) - - 1 -> { - val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - if (neighbor !is EndRodNode) return - - neighbor.positions += position - nodes[position] = neighbor - } - - // Should be a max of 2 - 2 -> { - // Get the larger - val wireNeighbors: MutableMap = mutableMapOf() - neighbors.mapNotNullTo(wireNeighbors) { (key, value) -> (value as? EndRodNode)?.let { key to value } } - - // Get the largest neighbor - val largestNeighbor = wireNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: return - - // Merge all other connected nodes into the largest - wireNeighbors.forEach { - it.value.drainTo(largestNeighbor, this.nodes) - } - - // Add this node - largestNeighbor.positions.add(position) - nodes[position] = largestNeighbor - } - - else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index 88010aa149..4bb0b22eaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.Consolidatable +import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT @@ -25,6 +26,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val pdc get() = manager.chunk.inner.persistentDataContainer protected abstract val namespacedKey: NamespacedKey + protected abstract val nodeFactory: NodeFactory<*> // val grids: Nothing = TODO("ChunkTransportNetwork system") @@ -36,10 +38,12 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { /** * Handle the creation / loading of the node into memory - * - * Inheritors may choose to save persistent data, or not **/ - abstract suspend fun createNodeFromBlock(block: BlockSnapshot) + open suspend fun createNodeFromBlock(block: BlockSnapshot) { + val key = toBlockKey(block.x, block.y, block.z) + + nodes[key] = nodeFactory.create(this, key, block) ?: return + } abstract fun processBlockRemoval(key: Long) abstract fun processBlockAddition(key: Long, new: BlockSnapshot) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt new file mode 100644 index 0000000000..03b2d06b9d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.node + +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +abstract class NodeFactory { + abstract suspend fun create(network: @UnsafeVariance T, key: BlockKey, snapshot: BlockSnapshot): TransportNode? +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 22051d191e..3bb5cf0434 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -2,8 +2,13 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.data.Directional import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -28,4 +33,13 @@ class EndRodNode() : MultiNode { override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } + + override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + + // Create new nodes, automatically merging together + positions.forEach { + val node = PowerNodeFactory.getNodeForPosition(network as ChunkPowerNetwork, getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) + network.nodes[it] = node + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt new file mode 100644 index 0000000000..39d87f94ba --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -0,0 +1,131 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.NodeFactory +import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.faces +import net.horizonsend.ion.server.miscellaneous.utils.filterValuesIsInstance +import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo +import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull +import org.bukkit.Material +import org.bukkit.block.BlockFace +import org.bukkit.block.data.Directional + +object PowerNodeFactory : NodeFactory() { + override suspend fun create(network: ChunkPowerNetwork, key: BlockKey, snapshot: BlockSnapshot): TransportNode? { + println("Triggering event") + + return when { + // Extract power from storage +// block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } + + // Add power to storage +// block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) + + // Straight wires + snapshot.type == Material.END_ROD -> getNodeForPosition(network, snapshot.data as Directional, key) + + // Omnidirectional wires + snapshot.type == Material.SPONGE -> addSpongeNode(network, key) + + // Merge node behavior +// block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) +// block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) + + // Split power evenly +// block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) + + // Redstone controlled gate +// block.type.isRedstoneLamp -> GateNode(this, x, y, z) + + // Power flow meter + + else -> throw NotImplementedError() + } + } + + fun addSpongeNode(network: ChunkPowerNetwork, position: BlockKey): SpongeNode { + val neighbors = getNeighborNodes(position, network.nodes).filterValuesIsInstance() + + when (neighbors.size) { + // New sponge node + 0 -> return SpongeNode(position) + // Consolidate into neighbor + 1 -> { + val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") + + neighbor.positions += position + return neighbor + } + + // Join multiple neighbors together + in 2..6 -> { + // Get the larger + val spongeNeighbors: MutableMap = mutableMapOf() + neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } + + // Get the largest neighbor + val largestNeighbor = spongeNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: throw ConcurrentModificationException("Node removed during processing") + + // Merge all other connected nodes into the largest + spongeNeighbors.forEach { + it.value.drainTo(largestNeighbor, network.nodes) + } + + // Add this node + largestNeighbor.positions.add(position) + return largestNeighbor + } + + else -> throw NotImplementedError() + } + } + + suspend fun getNodeForPosition(network: ChunkPowerNetwork, data: Directional, position: Long): EndRodNode { + val axis = data.facing.axis + + // The neighbors in the direction of the wire's facing, that are also facing that direction + val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()).filterKeys { + val relative = getRelative(position, it) + (getBlockSnapshotAsync(network.world, relative, false)?.data as? Directional)?.facing?.axis == axis + }.filterValuesIsInstance() + + when (neighbors.size) { + // Disconnected + 0 -> return EndRodNode(position) + + 1 -> { + val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") + neighbor.positions += position + + return neighbor + } + + // Should be a max of 2 + 2 -> { + // Get the larger + val wireNeighbors: MutableMap = mutableMapOf() + neighbors.mapNotNullTo(wireNeighbors) { (key, value) -> (value as? EndRodNode)?.let { key to value } } + + // Get the largest neighbor + val largestNeighbor = wireNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: throw ConcurrentModificationException("Node removed during processing") + + // Merge all other connected nodes into the largest + wireNeighbors.forEach { + it.value.drainTo(largestNeighbor, network.nodes) + } + + // Add this node + largestNeighbor.positions.add(position) + return largestNeighbor + } + + else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 51166b029f..076d5cca16 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -2,8 +2,11 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -13,15 +16,15 @@ import org.bukkit.persistence.PersistentDataType * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ class SpongeNode() : MultiNode { - constructor(origin: Long) : this() { + constructor(origin: BlockKey) : this() { positions.add(origin) } - override val positions: MutableSet = LongOpenHashSet() + override val positions: MutableSet = LongOpenHashSet() override val transferableNeighbors: MutableSet = ObjectOpenHashSet() - override fun isTransferable(position: Long, node: TransportNode): Boolean { + override fun isTransferable(position: BlockKey, node: TransportNode): Boolean { return true } @@ -33,4 +36,12 @@ class SpongeNode() : MultiNode { override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } + + override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + // Create new nodes, automatically merging together + positions.forEach { + val node = PowerNodeFactory.addSpongeNode(network as ChunkPowerNetwork, it) + network.nodes[it] = node + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt index 81220376fb..b64b3e1a12 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt @@ -45,7 +45,7 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 9a0ec2e5f0..4b2e955401 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey /** * A transport node that may cover many blocks to avoid making unnecessary steps @@ -11,9 +12,11 @@ interface MultiNode : TransportNode { /** * The positions occupied by the node **/ - val positions: MutableSet + val positions: MutableSet - override fun handleRemoval(network: ChunkTransportNetwork, position: Long) { + suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) + + override suspend fun handleRemoval(network: ChunkTransportNetwork, position: BlockKey) { network as ChunkPowerNetwork network.nodes.remove(position) @@ -24,16 +27,13 @@ interface MultiNode : TransportNode { network.nodes.remove(it) } - // Create new nodes, automatically merging together - positions.forEach { - network.addSpongeNode(it) - } + rebuildNode(network, position) } /** * Drain all the positions and connections to the provided node **/ - fun drainTo(new: MultiNode, nodes: MutableMap) { + fun drainTo(new: MultiNode, nodes: MutableMap) { new.positions.addAll(positions) new.transferableNeighbors.addAll(transferableNeighbors) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index 0a3bdc49c1..16b5a402eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -118,17 +118,6 @@ operator fun Pair.iterator(): Iterator = object : Iterator { } } -/** - * Set a value in a map, or remove it if provided null - **/ -fun MutableMap.setOrRemove(key: K, value: V?) { - if (value == null) { - remove(key) - } else { - set(key, value) - } -} - fun > MutableMap.popMaxByOrNull(selector: (Map.Entry) -> R): Map.Entry? { val max = maxByOrNull(selector) ?: return null remove(max.key) @@ -140,3 +129,13 @@ inline fun Iterable.associateWithNotNull(valueSelector: (K) -> V?): Ma @Suppress("UNCHECKED_CAST") return associateWith(valueSelector).filterValues { it != null } as Map } + +inline fun Map.filterValuesIsInstance(): Map { + @Suppress("UNCHECKED_CAST") + return filterValues { it is T } as Map +} + +inline fun Map.filterKeysIsInstance(): Map { + @Suppress("UNCHECKED_CAST") + return filterKeys { it is T } as Map +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt index 53bf22dde2..158910ef43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt @@ -43,22 +43,31 @@ fun BlockPos.toVec3i() = Vec3i(this.x, this.y, this.z) fun isValidYLevel(y: Int) = y in 0..Bukkit.getServer().worlds[0].maxHeight +/** + * A set of world coordinates packed into a 64-bit integer + * + * Cannot represent negative Y coordinates, deprecated in favor of Minecraft's method + * @see BlockKey + **/ +@Deprecated("Cannot represent negative Y coordinates, deprecated in favor of Minecraft's method via NewBlockKey") +typealias LegacyBlockKey = Long + @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") -fun blockKey(x: Number, y: Number, z: Number): Long = +fun blockKey(x: Number, y: Number, z: Number): LegacyBlockKey = x.toLong() and 134217727L or (z.toLong() and 134217727L shl 27) or (y.toLong() shl 54) // the reason i'm suppressing nothing to inline is that I thing it might have *some* performance benefits to inline the math @Suppress("NOTHING_TO_INLINE") @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") -inline fun blockKeyX(key: Long): Int = (key shl 37 shr 37).toInt() +inline fun blockKeyX(key: LegacyBlockKey): Int = (key shl 37 shr 37).toInt() @Suppress("NOTHING_TO_INLINE") @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") -inline fun blockKeyY(key: Long): Int = (key ushr 54).toInt() +inline fun blockKeyY(key: LegacyBlockKey): Int = (key ushr 54).toInt() @Suppress("NOTHING_TO_INLINE") @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") -inline fun blockKeyZ(key: Long): Int = (key shl 10 shr 37).toInt() +inline fun blockKeyZ(key: LegacyBlockKey): Int = (key shl 10 shr 37).toInt() fun distanceSquared(fromX: Double, fromY: Double, fromZ: Double, toX: Double, toY: Double, toZ: Double): Double = (fromX - toX).squared() + (fromY - toY).squared() + (fromZ - toZ).squared() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt index 904ea19756..ffb8fe055e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/NewBlockKey.kt @@ -4,17 +4,43 @@ import net.minecraft.core.BlockPos import org.bukkit.block.BlockFace /** - * Packs a x, y, z coordinate into a long + * A world coordinate packed into a 64-bit integer + * + * Capable of representing any coordinate in world bounds **/ -fun toBlockKey(x: Int, y: Int, z: Int): Long = BlockPos.asLong(x, y, z) -fun toBlockKey(vec3i: Vec3i): Long = BlockPos.asLong(vec3i.x, vec3i.y, vec3i.z) -fun toVec3i(key: Long): Vec3i = Vec3i(getX(key), getY(key), getZ(key)) +typealias BlockKey = Long -fun getX(key: Long) : Int = BlockPos.getX(key) -fun getY(key: Long) : Int = BlockPos.getY(key) -fun getZ(key: Long) : Int = BlockPos.getZ(key) +/** + * Packs a (x, y, z) coordinate into a long + **/ +fun toBlockKey(x: Int, y: Int, z: Int): BlockKey = BlockPos.asLong(x, y, z) + +/** + * Packs a (x, y, z) coordinate into a long + **/ +fun toBlockKey(vec3i: Vec3i): BlockKey = BlockPos.asLong(vec3i.x, vec3i.y, vec3i.z) + +/** + * Creates a Vec3i from a set of packed coordinates + **/ +fun toVec3i(key: BlockKey): Vec3i = Vec3i(getX(key), getY(key), getZ(key)) + +/** + * Get the X value of a packed coordinate + **/ +fun getX(key: BlockKey) : Int = BlockPos.getX(key) + +/** + * Get the Y value of a packed coordinate + **/ +fun getY(key: BlockKey) : Int = BlockPos.getY(key) + +/** + * Get the Z value of a packed coordinate + **/ +fun getZ(key: BlockKey) : Int = BlockPos.getZ(key) -fun getRelative(key: Long, direction: BlockFace, distance: Int = 1): Long = toBlockKey( +fun getRelative(key: BlockKey, direction: BlockFace, distance: Int = 1): BlockKey = toBlockKey( getX(key) + (direction.modX * distance), getY(key) + (direction.modY * distance), getZ(key) + (direction.modZ * distance) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt index a3eaaf3e0d..9785a91470 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Vec3i.kt @@ -10,7 +10,7 @@ class Vec3i: DBVec3i { constructor(a: DBVec3i) : super(a.x, a.y, a.z) constructor(x: Int, y: Int, z: Int) : super(x, y, z) @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") - constructor(blockKey: Long) : super(blockKeyX(blockKey), blockKeyY(blockKey), blockKeyZ(blockKey)) + constructor(blockKey: LegacyBlockKey) : super(blockKeyX(blockKey), blockKeyY(blockKey), blockKeyZ(blockKey)) constructor(vector: Vector) : super(vector.blockX, vector.blockY, vector.blockZ) @@ -21,7 +21,7 @@ class Vec3i: DBVec3i { fun toLocation(world: World): Location = Location(world, x.toDouble(), y.toDouble(), z.toDouble()) @Deprecated("Star Legacy's blockKey is not the same as Minecraft's blockKey") - fun toBlockKey(): Long = blockKey(x, y, z) + fun toBlockKey(): LegacyBlockKey = blockKey(x, y, z) fun toVector(): Vector = Vector(x, y, z) fun toCenterVector(): Vector = Vector(x.toDouble() + 0.5, y.toDouble() + 0.5, z.toDouble() + 0.5) From e482cfebf7daa42c638df74740c77acad86bd13f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 3 May 2024 02:07:58 -0500 Subject: [PATCH 035/500] add in more nodes --- .../transport/ChunkTransportManager.kt | 2 +- .../transport/grid/ChunkTransportNetwork.kt | 4 +- .../features/transport/node/NodeFactory.kt | 3 ++ .../transport/node/power/EndRodNode.kt | 2 +- .../node/power/PowerExtractorNode.kt | 6 +++ .../transport/node/power/PowerNodeFactory.kt | 47 +++++++++++++++---- .../transport/node/power/SolarPanelNode.kt | 6 +++ .../ion/server/features/world/IonChunk.kt | 2 +- 8 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 416b3f216e..bc9b440212 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -53,7 +53,7 @@ class ChunkTransportManager( processBlockRemoval(key) } - fun processBlockAdditon(event: BlockPlaceEvent) { + fun processBlockAddition(event: BlockPlaceEvent) { val block = event.block val key = toBlockKey(block.x, block.y, block.z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index 4bb0b22eaf..27814f7156 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -21,6 +21,8 @@ import java.util.concurrent.ConcurrentHashMap abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val nodes: ConcurrentHashMap = ConcurrentHashMap() + val extractors: ConcurrentHashMap = ConcurrentHashMap() + val world get() = manager.chunk.world val pdc get() = manager.chunk.inner.persistentDataContainer @@ -42,7 +44,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { open suspend fun createNodeFromBlock(block: BlockSnapshot) { val key = toBlockKey(block.x, block.y, block.z) - nodes[key] = nodeFactory.create(this, key, block) ?: return + nodeFactory.create(this, key, block) } abstract fun processBlockRemoval(key: Long) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index 03b2d06b9d..d941e50c9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -6,5 +6,8 @@ import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey abstract class NodeFactory { + /** + * Create and handle placement of a node at the position, if one should be created + **/ abstract suspend fun create(network: @UnsafeVariance T, key: BlockKey, snapshot: BlockSnapshot): TransportNode? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 3bb5cf0434..7ec18a39dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -38,7 +38,7 @@ class EndRodNode() : MultiNode { // Create new nodes, automatically merging together positions.forEach { - val node = PowerNodeFactory.getNodeForPosition(network as ChunkPowerNetwork, getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) + val node = PowerNodeFactory.addEndRod(network as ChunkPowerNetwork, getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) network.nodes[it] = node } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt new file mode 100644 index 0000000000..b68aff1642 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.transport.node.type.SingleNode + +class PowerExtractorNode() : SingleNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 39d87f94ba..ca3f1f4aec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -18,21 +18,26 @@ import org.bukkit.block.data.Directional object PowerNodeFactory : NodeFactory() { override suspend fun create(network: ChunkPowerNetwork, key: BlockKey, snapshot: BlockSnapshot): TransportNode? { - println("Triggering event") + val node = when { + // Straight wires + snapshot.type == Material.END_ROD -> addEndRod(network, snapshot.data as Directional, key) + + // Omnidirectional wires + snapshot.type == Material.SPONGE -> addSpongeNode(network, key) - return when { // Extract power from storage -// block.type == Material.CRAFTING_TABLE -> PowerExtractorNode(this, x, y, z).apply { extractors[toBlockKey(x, y, z)] = this } + snapshot.type == Material.CRAFTING_TABLE -> if (matchesSolarPanelStructure(snapshot, key)) { + createSolarPanel(network, key) + } else { + val node = createExtractorNode(network, key) + + network.extractors[key] = node + node + } // Add power to storage // block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) - // Straight wires - snapshot.type == Material.END_ROD -> getNodeForPosition(network, snapshot.data as Directional, key) - - // Omnidirectional wires - snapshot.type == Material.SPONGE -> addSpongeNode(network, key) - // Merge node behavior // block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) // block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) @@ -47,6 +52,10 @@ object PowerNodeFactory : NodeFactory() { else -> throw NotImplementedError() } + + network.nodes[key] = node + + return node } fun addSpongeNode(network: ChunkPowerNetwork, position: BlockKey): SpongeNode { @@ -86,7 +95,7 @@ object PowerNodeFactory : NodeFactory() { } } - suspend fun getNodeForPosition(network: ChunkPowerNetwork, data: Directional, position: Long): EndRodNode { + suspend fun addEndRod(network: ChunkPowerNetwork, data: Directional, position: Long): EndRodNode { val axis = data.facing.axis // The neighbors in the direction of the wire's facing, that are also facing that direction @@ -128,4 +137,22 @@ object PowerNodeFactory : NodeFactory() { else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") } } + + private suspend fun matchesSolarPanelStructure(blockSnapshot: BlockSnapshot, key: BlockKey): Boolean { + if (blockSnapshot.type != Material.CRAFTING_TABLE) return false + val diamond = getRelative(key, BlockFace.UP) + + if (getBlockSnapshotAsync(blockSnapshot.world, diamond)?.type != Material.DIAMOND_BLOCK) return false + val cell = getRelative(diamond, BlockFace.UP) + + return getBlockSnapshotAsync(blockSnapshot.world, cell)?.type == Material.DAYLIGHT_DETECTOR + } + + suspend fun createExtractorNode(network: ChunkPowerNetwork, key: BlockKey): PowerExtractorNode { + + } + + suspend fun createSolarPanel(network: ChunkPowerNetwork, key: BlockKey): SolarPanelNode { + + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt new file mode 100644 index 0000000000..3ba0f840ec --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import net.horizonsend.ion.server.features.transport.node.type.MultiNode + +class SolarPanelNode : MultiNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 0c5a1cd20b..901378b345 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -89,7 +89,7 @@ class IonChunk(val inner: Chunk) { @EventHandler fun onBlockBreak(event: BlockPlaceEvent) { val ionChunk = event.block.chunk.ion() - ionChunk.transportNetwork.processBlockAdditon(event) + ionChunk.transportNetwork.processBlockAddition(event) } /** From c9be01bebb2fb9826b5829ca4651e237cba2c466 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 3 May 2024 15:18:46 -0500 Subject: [PATCH 036/500] data fixers --- .../multiblock/MultiblockNameUpgrader.kt | 33 ++++++++++++ .../multiblock/MultiblockStructureFixer.kt | 50 +++++++++++++++++++ .../server/features/multiblock/Multiblocks.kt | 2 + .../entity/MultiblockEntityFixer.kt | 34 +++++++++++++ .../entity/MultiblockEntityInitializer.kt | 30 +++++++++++ .../ion/server/features/world/IonChunk.kt | 7 +++ .../features/world/data/ChunkDataFixer.kt | 15 ++++++ .../server/features/world/data/DataFixer.kt | 5 ++ 8 files changed, 176 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt new file mode 100644 index 0000000000..09d7a9172c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt @@ -0,0 +1,33 @@ +package net.horizonsend.ion.server.features.multiblock + +import net.horizonsend.ion.server.features.world.data.DataFixer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataType + +object MultiblockNameUpgrader : DataFixer { + private val upgraders: MutableMap = mutableMapOf() + + override fun registerFixers() { + registerUpgrader("NavigationComputerMultiblockAdvanced", "HorizontalNavigationComputerMultiblockAdvanced") + } + + private fun registerUpgrader(previous: String, new: String) { + upgraders[previous] = new + } + + fun upgrade(sign: Sign) { + var nextName: String? = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return + var newName: String? = null + + while (nextName != null) { + newName = nextName + nextName = upgraders[nextName] + } + + if (newName == null) return + sign.persistentDataContainer.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, newName) + Tasks.syncBlocking { sign.update() } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt new file mode 100644 index 0000000000..7287adcf10 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt @@ -0,0 +1,50 @@ +package net.horizonsend.ion.server.features.multiblock + +import net.horizonsend.ion.server.features.world.data.DataFixer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataType + +/** + * Upgrades a multiblock's structure to a new version, before detection + **/ +object MultiblockStructureFixer : DataFixer { + /** + * Map of multiblock identifying strings to upgraders + **/ + private val fixers = mutableMapOf() + + override fun registerFixers() { + + } + + fun upgrade(sign: Sign): Boolean { + val name = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return false + + return upgrade(sign) + } + + private class StructureUpgrader( + override val multiblock: Multiblock, + override val dataVersion: Int, + val previousShape: MultiblockShape, + val newShape: MultiblockShape + ) : MultiblockUpgrader { + override fun apply(sign: Sign) { + //TODO + } + } + + private class SignUpgrader(override val multiblock: Multiblock, override val dataVersion: Int) : MultiblockUpgrader { + override fun apply(sign: Sign) { + //TODO + } + } + + private sealed interface MultiblockUpgrader { + val dataVersion: Int + val multiblock: Multiblock + + fun apply(sign: Sign) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index e50e0c615b..adf6cab8cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -355,6 +355,7 @@ object Multiblocks : IonServerComponent() { /** Check if a sign has been registered as a multiblock, if so, return that value */ fun getFromPDC(sign: Sign): Multiblock? { + MultiblockNameUpgrader.upgrade(sign) return getFromPDC(sign.persistentDataContainer) } @@ -421,6 +422,7 @@ object Multiblocks : IonServerComponent() { if (cached != null) return cached val sign = getBukkitBlockState(block, loadChunks) as? Sign ?: return null + MultiblockNameUpgrader.upgrade(sign) for ((name, multiblock) in multiblocks) { if (!matchesPersistentDataContainer(sign.persistentDataContainer, multiblock)) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt new file mode 100644 index 0000000000..e3201aeaf8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.multiblock.entity + +import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.features.world.data.DataFixer + +object MultiblockEntityFixer : DataFixer { + private val fixers: MutableList> = mutableListOf() + + private fun addDataUpgrader(name: String, dataVersion: Int, apply: T.() -> Unit) { + fixers.add(DataUpgrader(name, dataVersion, apply)) + } + + override fun registerFixers() { + // Don't need any yet + } + + private class DataUpgrader(@Suppress("unused") val name: String, val dataVersion: Int, private val applicator: T.() -> Unit) { + fun apply(multiblock: T) = applicator.invoke(multiblock) + } + + fun upgrade(chunk: IonChunk) { + chunk.multiblockManager.getAllMultiblockEntities().values.forEach { + upgrade(it, chunk.dataVersion) + } + } + + fun upgrade(multiblockEntity: T, dataVersion: Int) { + val fixersFor = fixers + .filterIsInstance>() + .filter { it.dataVersion > dataVersion } + + fixersFor.forEach { it.apply(multiblockEntity) } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt new file mode 100644 index 0000000000..93b7fcbaa3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.multiblock.entity + +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.world.data.DataFixer +import org.bukkit.block.Sign + +/** + * Migrates multiblocks without entities to + **/ +object MultiblockEntityInitializer : DataFixer { + private val initializers: MutableMap> = mutableMapOf() + + override fun registerFixers() { + + } + + private class Initializer(@Suppress("unused") val name: String, private val applicator: Sign.() -> T) { + fun apply(multiblock: Sign): T = applicator.invoke(multiblock) + } + + fun upgrade(sign: Sign, entityManager: ChunkMultiblockManager) { + val multiblock = Multiblocks.getFromPDC(sign) ?: return + val initializer = initializers[multiblock] ?: return + + val multiblockEntity = initializer.apply(sign) + entityManager.addMultiblockEntity(multiblockEntity) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 901378b345..3be60b85d1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -3,7 +3,9 @@ package net.horizonsend.ion.server.features.world import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.data.ChunkDataFixer import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.world.level.chunk.LevelChunkSection import org.bukkit.Chunk @@ -13,8 +15,10 @@ import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent +import org.bukkit.persistence.PersistentDataType.INTEGER class IonChunk(val inner: Chunk) { + val dataVersion = inner.persistentDataContainer.getOrDefault(NamespacedKeys.DATA_VERSION, INTEGER, 0) val locationKey = inner.chunkKey /** The origin X coordinate of this chunk (in real coordinates) **/ @@ -106,6 +110,9 @@ class IonChunk(val inner: Chunk) { ionChunk.onLoad() + // Upgrade data after it has been loaded + ChunkDataFixer.upgrade(ionChunk) + return ionChunk } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt new file mode 100644 index 0000000000..b882e55fe7 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.world.data + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntityFixer +import net.horizonsend.ion.server.features.world.IonChunk + +object ChunkDataFixer { + const val DATA_VERSION = 1 + + fun upgrade(chunk: IonChunk) { + if (chunk.dataVersion == DATA_VERSION) return + if (chunk.dataVersion > DATA_VERSION) throw IllegalStateException("Invalid chunk data version!") + + MultiblockEntityFixer.upgrade(chunk) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt new file mode 100644 index 0000000000..fc13289c14 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.world.data + +interface DataFixer { + fun registerFixers() +} From ac82355abc26e0c015d63d02b6f270f6e289ed93 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 4 May 2024 00:46:40 -0500 Subject: [PATCH 037/500] solar panel work --- .../transport/node/power/PowerNodeFactory.kt | 21 +++++-- .../transport/node/power/SolarPanelNode.kt | 57 +++++++++++++++++++ .../transport/node/power/SpongeNode.kt | 2 +- .../persistence/NamespacedKeys.kt | 1 + 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index ca3f1f4aec..83ce92e2d9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -23,13 +24,13 @@ object PowerNodeFactory : NodeFactory() { snapshot.type == Material.END_ROD -> addEndRod(network, snapshot.data as Directional, key) // Omnidirectional wires - snapshot.type == Material.SPONGE -> addSpongeNode(network, key) + snapshot.type == Material.SPONGE -> addSponge(network, key) // Extract power from storage snapshot.type == Material.CRAFTING_TABLE -> if (matchesSolarPanelStructure(snapshot, key)) { - createSolarPanel(network, key) + addSolarPanel(network, key) } else { - val node = createExtractorNode(network, key) + val node = addExtractor(network, key) network.extractors[key] = node node @@ -58,7 +59,7 @@ object PowerNodeFactory : NodeFactory() { return node } - fun addSpongeNode(network: ChunkPowerNetwork, position: BlockKey): SpongeNode { + fun addSponge(network: ChunkPowerNetwork, position: BlockKey): SpongeNode { val neighbors = getNeighborNodes(position, network.nodes).filterValuesIsInstance() when (neighbors.size) { @@ -148,11 +149,19 @@ object PowerNodeFactory : NodeFactory() { return getBlockSnapshotAsync(blockSnapshot.world, cell)?.type == Material.DAYLIGHT_DETECTOR } - suspend fun createExtractorNode(network: ChunkPowerNetwork, key: BlockKey): PowerExtractorNode { + suspend fun addExtractor(network: ChunkPowerNetwork, key: BlockKey): PowerExtractorNode { } - suspend fun createSolarPanel(network: ChunkPowerNetwork, key: BlockKey): SolarPanelNode { + suspend fun addSolarPanel(network: ChunkPowerNetwork, key: BlockKey): SolarPanelNode { + val neighbors = CARDINAL_BLOCK_FACES.flatMap { direction -> + val relativeSide = getRelative(key, direction) + + (-1..3).map { + getRelative(relativeSide, BlockFace.UP, it) + } + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 3ba0f840ec..5be825961c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -1,6 +1,63 @@ package net.horizonsend.ion.server.features.transport.node.power +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_COUNT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType.INTEGER +import org.bukkit.persistence.PersistentDataType.LONG_ARRAY +/** + * Represents a solar panel, or multiple + **/ class SolarPanelNode : MultiNode { + /** The number of solar cells contained in this node */ + private var cellNumber: Int = 1 + override val positions: MutableSet = LongOpenHashSet() + + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + + override fun isTransferable(position: Long, node: TransportNode): Boolean { + TODO("Not yet implemented") + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(SOLAR_CELL_COUNT, INTEGER, cellNumber) + persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + cellNumber = persistentDataContainer.getOrDefault(SOLAR_CELL_COUNT, INTEGER, 1) + val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } + } + + override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + // Create new nodes, automatically merging together + positions.forEach { + val node = PowerNodeFactory.addSolarPanel(network as ChunkPowerNetwork, it) + network.nodes[it] = node + } + } + + private var lastTicked: Long = System.currentTimeMillis() + + /** + * Returns the amount of power between ticks + **/ + fun getPower(): Int { + val time = System.currentTimeMillis() + val diff = time - this.lastTicked + + return ((diff / 1000.0) * POWER_PER_SECOND).toInt() * cellNumber + } + + companion object { + const val POWER_PER_SECOND = 50 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 076d5cca16..01d6e30be7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -40,7 +40,7 @@ class SpongeNode() : MultiNode { override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { // Create new nodes, automatically merging together positions.forEach { - val node = PowerNodeFactory.addSpongeNode(network as ChunkPowerNetwork, it) + val node = PowerNodeFactory.addSponge(network as ChunkPowerNetwork, it) network.nodes[it] = node } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index e219b69591..fae554b696 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -95,6 +95,7 @@ object NamespacedKeys { val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") val NODE_COVERED_POSITIONS = key("node_covered_positions") + val SOLAR_CELL_COUNT = key("solar_cell_count") val NODE_TYPE = key("node_type") val NODES = key("chunk_power_nodes") From c9aed5e2ceb8940c79c142f5046c6a936bc9a66d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 5 May 2024 01:36:09 -0500 Subject: [PATCH 038/500] solar panels --- .../server/command/admin/IonChunkCommand.kt | 13 +- .../features/transport/node/NodeFactory.kt | 3 +- .../features/transport/node/NodeType.kt | 4 + .../transport/node/power/EndRodNode.kt | 5 +- .../node/power/PowerExtractorNode.kt | 4 +- .../transport/node/power/PowerNodeFactory.kt | 141 ++++++++++++------ .../transport/node/power/SolarPanelNode.kt | 110 +++++++++++++- .../transport/node/power/SpongeNode.kt | 5 +- .../features/transport/node/type/MultiNode.kt | 27 +++- .../persistence/NamespacedKeys.kt | 1 + .../server/miscellaneous/utils/Collections.kt | 22 --- 11 files changed, 241 insertions(+), 94 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 2a305cf751..925724fdd0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -74,7 +74,6 @@ object IonChunkCommand : SLCommand() { grid.nodes.forEach { (t, u) -> val vec = toVec3i(t) - println(u) sender.highlightBlock(vec, 50L) } } @@ -91,11 +90,15 @@ object IonChunkCommand : SLCommand() { else -> return@launch fail { "invalid network" } } - for (x in 0..15) for (y in ionChunk.world.minHeight..ionChunk.world.maxHeight) for (z in 0..15) { - val realX = x + ionChunk.originX - val realZ = z + ionChunk.originZ + grid.nodes.clear() + grid.extractors.clear() - grid.createNodeFromBlock(getBlockSnapshotAsync(sender.world, realX, y, realZ)!!) + for (x in ionChunk.originX ..ionChunk.originX + 15) { + for (z in ionChunk.originZ..ionChunk.originZ + 15) { + for (y in ionChunk.world.minHeight until ionChunk.world.maxHeight) { + grid.createNodeFromBlock(getBlockSnapshotAsync(sender.world, x, y, z)!!) + } + } } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index d941e50c9c..57ab637971 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -2,12 +2,11 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey abstract class NodeFactory { /** * Create and handle placement of a node at the position, if one should be created **/ - abstract suspend fun create(network: @UnsafeVariance T, key: BlockKey, snapshot: BlockSnapshot): TransportNode? + abstract suspend fun create(network: @UnsafeVariance T, key: BlockKey, snapshot: BlockSnapshot) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 1aa7811c12..7d9e183aef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,12 +1,16 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.node.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.features.transport.node.power.TransportNode enum class NodeType(val clazz: Class) { //POWER SPONGE_NODE(SpongeNode::class.java), + END_ROD_NODE(EndRodNode::class.java), + SOLAR_PANEL_NODE(SolarPanelNode::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 7ec18a39dc..84f30c8392 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -12,7 +12,7 @@ import org.bukkit.block.data.Directional import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class EndRodNode() : MultiNode { +class EndRodNode() : MultiNode { constructor(origin: Long) : this() { positions.add(origin) } @@ -38,8 +38,7 @@ class EndRodNode() : MultiNode { // Create new nodes, automatically merging together positions.forEach { - val node = PowerNodeFactory.addEndRod(network as ChunkPowerNetwork, getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) - network.nodes[it] = node + PowerNodeFactory.addEndRod(network as ChunkPowerNetwork, getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index b68aff1642..990cf0424b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,6 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.node.type.SingleNode - -class PowerExtractorNode() : SingleNode { +class PowerExtractorNode() { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 83ce92e2d9..e40eb4e962 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -5,7 +5,9 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode.Companion.matchesSolarPanelStructure import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -15,11 +17,14 @@ import net.horizonsend.ion.server.miscellaneous.utils.mapNotNullTo import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull import org.bukkit.Material import org.bukkit.block.BlockFace +import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.data.Directional object PowerNodeFactory : NodeFactory() { - override suspend fun create(network: ChunkPowerNetwork, key: BlockKey, snapshot: BlockSnapshot): TransportNode? { - val node = when { + override suspend fun create(network: ChunkPowerNetwork, key: BlockKey, snapshot: BlockSnapshot) { + if (network.nodes.contains(key)) return + + when { // Straight wires snapshot.type == Material.END_ROD -> addEndRod(network, snapshot.data as Directional, key) @@ -27,13 +32,25 @@ object PowerNodeFactory : NodeFactory() { snapshot.type == Material.SPONGE -> addSponge(network, key) // Extract power from storage - snapshot.type == Material.CRAFTING_TABLE -> if (matchesSolarPanelStructure(snapshot, key)) { + snapshot.type == Material.CRAFTING_TABLE -> if (matchesSolarPanelStructure(network.world, key)) { addSolarPanel(network, key) } else { - val node = addExtractor(network, key) + addExtractor(network, key) + } + + // Check for extractor beneath + snapshot.type == Material.DIAMOND_BLOCK -> { + val extractorKey = getRelative(key, DOWN, 1) + if (matchesSolarPanelStructure(network.world, extractorKey)) { + addSolarPanel(network, extractorKey) + } + } - network.extractors[key] = node - node + snapshot.type == Material.DAYLIGHT_DETECTOR -> { + val extractorKey = getRelative(key, DOWN, 2) + if (matchesSolarPanelStructure(network.world, extractorKey)) { + addSolarPanel(network, extractorKey) + } } // Add power to storage @@ -51,26 +68,23 @@ object PowerNodeFactory : NodeFactory() { // Power flow meter - else -> throw NotImplementedError() + else -> return } - - network.nodes[key] = node - - return node } - fun addSponge(network: ChunkPowerNetwork, position: BlockKey): SpongeNode { + fun addSponge(network: ChunkPowerNetwork, position: BlockKey) { val neighbors = getNeighborNodes(position, network.nodes).filterValuesIsInstance() when (neighbors.size) { // New sponge node - 0 -> return SpongeNode(position) + 0 -> { + network.nodes[position] = SpongeNode(position) + } + // Consolidate into neighbor 1 -> { val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - - neighbor.positions += position - return neighbor + neighbor.addPosition(network, position) } // Join multiple neighbors together @@ -84,19 +98,18 @@ object PowerNodeFactory : NodeFactory() { // Merge all other connected nodes into the largest spongeNeighbors.forEach { - it.value.drainTo(largestNeighbor, network.nodes) + it.value.drainTo(network, largestNeighbor) } // Add this node - largestNeighbor.positions.add(position) - return largestNeighbor + largestNeighbor.addPosition(network, position) } else -> throw NotImplementedError() } } - suspend fun addEndRod(network: ChunkPowerNetwork, data: Directional, position: Long): EndRodNode { + suspend fun addEndRod(network: ChunkPowerNetwork, data: Directional, position: Long) { val axis = data.facing.axis // The neighbors in the direction of the wire's facing, that are also facing that direction @@ -107,13 +120,13 @@ object PowerNodeFactory : NodeFactory() { when (neighbors.size) { // Disconnected - 0 -> return EndRodNode(position) + 0 -> { + network.nodes[position] = EndRodNode(position) + } 1 -> { val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - neighbor.positions += position - - return neighbor + neighbor.addPosition(network, position) } // Should be a max of 2 @@ -127,41 +140,83 @@ object PowerNodeFactory : NodeFactory() { // Merge all other connected nodes into the largest wireNeighbors.forEach { - it.value.drainTo(largestNeighbor, network.nodes) + it.value.drainTo(network, largestNeighbor) } // Add this node - largestNeighbor.positions.add(position) - return largestNeighbor + largestNeighbor.addPosition(network, position) } else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") } } - private suspend fun matchesSolarPanelStructure(blockSnapshot: BlockSnapshot, key: BlockKey): Boolean { - if (blockSnapshot.type != Material.CRAFTING_TABLE) return false - val diamond = getRelative(key, BlockFace.UP) - - if (getBlockSnapshotAsync(blockSnapshot.world, diamond)?.type != Material.DIAMOND_BLOCK) return false - val cell = getRelative(diamond, BlockFace.UP) - - return getBlockSnapshotAsync(blockSnapshot.world, cell)?.type == Material.DAYLIGHT_DETECTOR + suspend fun addExtractor(network: ChunkPowerNetwork, key: BlockKey) { +// when () { +// +// } } - suspend fun addExtractor(network: ChunkPowerNetwork, key: BlockKey): PowerExtractorNode { + /** + * Provided the key of the extractor, create or combine solar panel nodes + **/ + suspend fun addSolarPanel(network: ChunkPowerNetwork, position: BlockKey) { + // The diamond and daylight detector + val panelPositions = (1..2).map { getRelative(position, BlockFace.UP, it) } + + // Get the nodes that might be touching the solar panel + // + // 2d cross-section for demonstration: C is the origin crafting table, X are positions checked + // + // X X + // X X + // X C X + // X X + + // If another solar panel is found at any of those positions, handle merges + val neighboringNodes = CARDINAL_BLOCK_FACES.associateWithNotNull { direction -> + val relativeSide = getRelative(position, direction) + + (-1..3).firstNotNullOfOrNull { + val neighborKey = getRelative(relativeSide, BlockFace.UP, it) + val node = network.nodes[neighborKey] + if (node !is SolarPanelNode) return@firstNotNullOfOrNull null + + // Take only extractor locations + node.takeIf { node.isIntact(network.world, neighborKey) } + } + }.toMutableMap() - } + when (neighboringNodes.size) { + 0 -> { + val node = SolarPanelNode() - suspend fun addSolarPanel(network: ChunkPowerNetwork, key: BlockKey): SolarPanelNode { - val neighbors = CARDINAL_BLOCK_FACES.flatMap { direction -> - val relativeSide = getRelative(key, direction) + // Add new position + node.addPosition(network, position, panelPositions) + } - (-1..3).map { - getRelative(relativeSide, BlockFace.UP, it) + 1 -> { + val neighbor = neighboringNodes.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") + + // Add new position to neighbor + neighbor.addPosition(network, position, panelPositions) } - } + in 2..4 -> { + val largestNeighbor = neighboringNodes + .popMaxByOrNull { it.value.positions.size } + ?.value ?: throw ConcurrentModificationException("Node removed during processing") + // Merge all other connected nodes into the largest + neighboringNodes.forEach { + it.value.drainTo(network, largestNeighbor) + } + + // Add this node + largestNeighbor.addPosition(network, position, panelPositions) + } + + else -> throw IllegalArgumentException() + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 5be825961c..dcb214c9a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -2,23 +2,34 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_COUNT +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG_ARRAY +import kotlin.math.PI +import kotlin.math.max +import kotlin.math.sin /** * Represents a solar panel, or multiple **/ -class SolarPanelNode : MultiNode { +class SolarPanelNode : MultiNode { /** The number of solar cells contained in this node */ - private var cellNumber: Int = 1 + var cellNumber: Int = 1 override val positions: MutableSet = LongOpenHashSet() + /** The positions of extractors in this solar panel */ + val extractorPositions = LongOpenHashSet() override val transferableNeighbors: MutableSet = ObjectOpenHashSet() @@ -29,35 +40,120 @@ class SolarPanelNode : MultiNode { override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(SOLAR_CELL_COUNT, INTEGER, cellNumber) persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) + persistentDataContainer.set(SOLAR_CELL_EXTRACTORS, LONG_ARRAY, extractorPositions.toLongArray()) } override fun loadData(persistentDataContainer: PersistentDataContainer) { cellNumber = persistentDataContainer.getOrDefault(SOLAR_CELL_COUNT, INTEGER, 1) + val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, LONG_ARRAY) coveredPositions?.let { positions.addAll(it.asIterable()) } + + val extractors = persistentDataContainer.get(SOLAR_CELL_EXTRACTORS, LONG_ARRAY) + extractors?.let { extractorPositions.addAll(it.asIterable()) } + } + + override suspend fun handleRemoval(network: ChunkTransportNetwork, position: BlockKey) { + // Need to handle the extractor positions manually + when { + // Removed extractor, easier to find + extractorPositions.contains(position) -> removePosition( + network as ChunkPowerNetwork, + position, + listOf(getRelative(position, BlockFace.UP, 1), getRelative(position, BlockFace.UP, 2)) + ) + + // Need to find extractor, search downward form position + else -> { + val extractorPosition: BlockKey = (0..2).firstNotNullOf { y -> + getRelative(position, BlockFace.DOWN, y).takeIf { extractorPositions.contains(it) } + } + + removePosition( + network as ChunkPowerNetwork, + extractorPosition, + listOf(getRelative(extractorPosition, BlockFace.UP, 1), getRelative(extractorPosition, BlockFace.UP, 2)) + ) + } + } + + rebuildNode(network, position) + } + + fun addPosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { + extractorPositions += extractorKey + addPosition(network, extractorKey) + + positions += others + for (position: BlockKey in positions) { + network.nodes[position] = this + } + + cellNumber++ + } + + fun removePosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { + extractorPositions -= extractorKey + network.nodes.remove(extractorKey) + positions.remove(extractorKey) + + positions += others + for (position: BlockKey in positions) { + network.nodes.remove(position) + } + + cellNumber-- } override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { // Create new nodes, automatically merging together - positions.forEach { - val node = PowerNodeFactory.addSolarPanel(network as ChunkPowerNetwork, it) - network.nodes[it] = node + extractorPositions.forEach { + PowerNodeFactory.addSolarPanel(network as ChunkPowerNetwork, it) } } + override fun drainTo(network: ChunkTransportNetwork, new: SolarPanelNode) { + super.drainTo(network, new) + + new.extractorPositions.addAll(extractorPositions) + new.cellNumber += cellNumber + } + private var lastTicked: Long = System.currentTimeMillis() /** * Returns the amount of power between ticks **/ - fun getPower(): Int { + fun getPower(network: ChunkPowerNetwork): Int { + val daylightMultiplier: Double = if (network.world.environment == World.Environment.NORMAL) { + val daylight = sin((network.world.time / (12000.0 / PI)) - (PI / 2)) + max(0.0, daylight) + } else 0.5 + val time = System.currentTimeMillis() val diff = time - this.lastTicked - return ((diff / 1000.0) * POWER_PER_SECOND).toInt() * cellNumber + return ((diff / 1000.0) * 5 * cellNumber * daylightMultiplier).toInt() + } + + /** + * Returns whether the individual solar panel from the extractor location is intact + **/ + suspend fun isIntact(world: World, extractorKey: BlockKey): Boolean { + return matchesSolarPanelStructure(world, extractorKey) } companion object { const val POWER_PER_SECOND = 50 + + suspend fun matchesSolarPanelStructure(world: World, key: BlockKey): Boolean { + if (getBlockSnapshotAsync(world, key)?.type != Material.CRAFTING_TABLE) return false + val diamond = getRelative(key, BlockFace.UP) + + if (getBlockSnapshotAsync(world, diamond)?.type != Material.DIAMOND_BLOCK) return false + val cell = getRelative(diamond, BlockFace.UP) + + return getBlockSnapshotAsync(world, cell)?.type == Material.DAYLIGHT_DETECTOR + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 01d6e30be7..39f831c933 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -15,7 +15,7 @@ import org.bukkit.persistence.PersistentDataType * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode() : MultiNode { +class SpongeNode() : MultiNode { constructor(origin: BlockKey) : this() { positions.add(origin) } @@ -40,8 +40,7 @@ class SpongeNode() : MultiNode { override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { // Create new nodes, automatically merging together positions.forEach { - val node = PowerNodeFactory.addSponge(network as ChunkPowerNetwork, it) - network.nodes[it] = node + PowerNodeFactory.addSponge(network as ChunkPowerNetwork, it) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 4b2e955401..3edb5653ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey /** * A transport node that may cover many blocks to avoid making unnecessary steps **/ -interface MultiNode : TransportNode { +interface MultiNode, T: MultiNode> : TransportNode { /** * The positions occupied by the node **/ @@ -30,16 +30,31 @@ interface MultiNode : TransportNode { rebuildNode(network, position) } + /** + * Adds new a position to this node + **/ + fun addPosition(network: ChunkTransportNetwork, position: BlockKey) { + positions += position + network.nodes[position] = this + } + + /** + * Adds new a position to this node + **/ + fun addPositions(network: ChunkTransportNetwork, newPositions: Iterable) { + for (position in newPositions) { + positions += position + network.nodes[position] = this + } + } + /** * Drain all the positions and connections to the provided node **/ - fun drainTo(new: MultiNode, nodes: MutableMap) { - new.positions.addAll(positions) + fun drainTo(network: ChunkTransportNetwork, new: Self) { new.transferableNeighbors.addAll(transferableNeighbors) - for (position in positions) { - nodes[position] = new - } + new.addPositions(network, positions) } override fun handlePlacement(network: ChunkTransportNetwork) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index fae554b696..e771ebcd0b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -96,6 +96,7 @@ object NamespacedKeys { val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") val NODE_COVERED_POSITIONS = key("node_covered_positions") val SOLAR_CELL_COUNT = key("solar_cell_count") + val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") val NODE_TYPE = key("node_type") val NODES = key("chunk_power_nodes") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index 16b5a402eb..fcad572846 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -50,28 +50,6 @@ fun Collection>.toMap(): Map { fun List.safeSubList(fromIndex: Int, toIndex: Int): List = this.subList(fromIndex.coerceAtLeast(this.size), toIndex.coerceAtMost(this.size)) -/** - * Returns a [List] containing all key-value pairs. - */ -fun Map.toMutableList(): MutableList> { - if (isEmpty()) return mutableListOf() - - val iterator = entries.iterator() - if (!iterator.hasNext()) return mutableListOf() - - val first = iterator.next() - if (!iterator.hasNext()) return mutableListOf(first.toPair()) - - val result = ArrayList>(size) - result.add(first.toPair()) - - do { - result.add(iterator.next().toPair()) - } while (iterator.hasNext()) - - return result -} - fun Map.mapTo(other: MutableMap, transform: (Map.Entry) -> Pair) = other.putAll(map(transform)) fun Map.mapNotNullTo(other: MutableMap, transform: (Map.Entry) -> Pair?) = other.putAll(map(transform).filterNotNull()) fun MutableSet.and(vararg others: T): MutableSet = apply { others.forEach { add(it) } } From cd93e9ff52ff05088a05702197ac7527991f29ba Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 5 May 2024 02:10:10 -0500 Subject: [PATCH 039/500] cleanup, extractor and input --- .../entity/type/PoweredMultiblockEntity.kt | 2 + .../transport/grid/ChunkTransportNetwork.kt | 3 +- .../features/transport/node/Consolidatable.kt | 11 --- .../features/transport/node/ExtractorNode.kt | 17 ---- .../features/transport/node/GridNode.kt | 85 ------------------- .../features/transport/node/NodeType.kt | 4 + .../node/power/PowerExtractorNode.kt | 29 ++++++- .../transport/node/power/PowerInputNode.kt | 40 +++++++++ .../transport/node/power/PowerNodeFactory.kt | 14 +-- .../transport/node/power/SolarPanelNode.kt | 8 +- .../features/transport/step/PowerStep.kt | 13 --- .../server/features/transport/step/Step.kt | 7 -- .../persistence/NamespacedKeys.kt | 1 + 13 files changed, 91 insertions(+), 143 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index cbf563612e..9ebcf352e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -3,12 +3,14 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { + val position: BlockKey var powerUnsafe: Int val type: PowerStoringMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index 27814f7156..367d1d5b73 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.Consolidatable import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES @@ -145,7 +144,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { **/ private fun finalizeNodes() { nodes.forEach { (_, node) -> - if (node is Consolidatable) node.consolidate() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt deleted file mode 100644 index f4ba54c9be..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/Consolidatable.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -/** - * A node that may be consolidated. - **/ -interface Consolidatable { - /** - * Consolidates this node if possible - **/ - fun consolidate() -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt deleted file mode 100644 index a24822724b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/ExtractorNode.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -abstract class ExtractorNode( - override val parentTransportNetwork: ChunkTransportNetwork, - override val x: Int, - override val y: Int, - override val z: Int, -) : GridNode { - override val transferableNeighbors: ConcurrentHashMap = ConcurrentHashMap() - - abstract fun getExtractableInventories(): Collection> -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt deleted file mode 100644 index 331f951710..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/GridNode.kt +++ /dev/null @@ -1,85 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap - -interface GridNode { - val parentTransportNetwork: ChunkTransportNetwork - val x: Int - val y: Int - val z: Int - - val key get() = toBlockKey(x, y, z) - - val transferableNeighbors: ConcurrentHashMap - - /** - * Collects the neighbors of this node - **/ - fun collectNeighbors() { - - } - - /** - * Notify neighbors of this node's existence - **/ - fun notifyNeighbors() { - // In every adjacent direction - for (direction in ADJACENT_BLOCK_FACES) { - val newX = x + direction.modX - val newY = y + direction.modY - val newZ = z + direction.modZ - - // All nodes should already be collected - val possibleNode = parentTransportNetwork.getNode(newX, newY, newZ) ?: continue - - possibleNode.transferableNeighbors.clear() - } - } - - /** - * Notifies this node of a changed neighbor - * - * Will handle adding it to the transferable list, if able - **/ - fun neighborChanged(offset: BlockFace, replacement: GridNode?) { - if (replacement != null) { - if (!isTransferableTo(offset, replacement)) return - - transferableNeighbors[offset] = replacement - } else { - transferableNeighbors.remove(offset) - } - } - - /** - * Whether a power transfer may take place between these two nodes - * - * Used when initially building relations - **/ - fun isTransferableTo(offset: BlockFace, node: GridNode): Boolean - - /** - * Returns a possible neighbor of this node - **/ - fun getNeighbor(face: BlockFace): GridNode? { - return transferableNeighbors[face] - } - - /** - * Replace this node with another and update its neighbors - **/ - fun replace(new: GridNode?) { -// for ((offset, neighbor) in transferableNeighbors) { -// neighbor.neighborChanged(offset.oppositeFace, new) -// -// parentTransportNetwork.nodes.setOrRemove(key, new) -// } - } - - fun processStep(step: Step) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 7d9e183aef..d00b09774d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.features.transport.node.power.TransportNode @@ -11,6 +13,8 @@ enum class NodeType(val clazz: Class) { SPONGE_NODE(SpongeNode::class.java), END_ROD_NODE(EndRodNode::class.java), SOLAR_PANEL_NODE(SolarPanelNode::class.java), + POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), + POWER_INPUT_NODE(PowerInputNode::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 990cf0424b..9fd3a57f53 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,4 +1,31 @@ package net.horizonsend.ion.server.features.transport.node.power -class PowerExtractorNode() { +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +class PowerExtractorNode() : SingleNode { + constructor(position: BlockKey) : this() { + this.position = position + } + + override var position by Delegates.notNull() + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + + override fun isTransferable(position: Long, node: TransportNode): Boolean { + TODO("Not yet implemented") + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } } + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt new file mode 100644 index 0000000000..d77d9ce70c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -0,0 +1,40 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_DESTINATIONS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +class PowerInputNode() : SingleNode { + constructor(position: BlockKey) : this() { + this.position = position + } + + override var position by Delegates.notNull() + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + + /** + * Multiblocks that share this power input + **/ + val multiblockPositions: MutableSet = LongOpenHashSet() + + override fun isTransferable(position: Long, node: TransportNode): Boolean { + TODO("Not yet implemented") + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + persistentDataContainer.set(MULTIBLOCK_DESTINATIONS, PersistentDataType.LONG_ARRAY, multiblockPositions.toLongArray()) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + + multiblockPositions.addAll(persistentDataContainer.getOrDefault(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, longArrayOf()).toList()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index e40eb4e962..204ff3447b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -41,6 +41,7 @@ object PowerNodeFactory : NodeFactory() { // Check for extractor beneath snapshot.type == Material.DIAMOND_BLOCK -> { val extractorKey = getRelative(key, DOWN, 1) + network.nodes.remove(extractorKey) if (matchesSolarPanelStructure(network.world, extractorKey)) { addSolarPanel(network, extractorKey) } @@ -48,13 +49,14 @@ object PowerNodeFactory : NodeFactory() { snapshot.type == Material.DAYLIGHT_DETECTOR -> { val extractorKey = getRelative(key, DOWN, 2) + network.nodes.remove(extractorKey) if (matchesSolarPanelStructure(network.world, extractorKey)) { addSolarPanel(network, extractorKey) } } // Add power to storage -// block.type == Material.NOTE_BLOCK -> PowerInputNode(this, x, y, z) + snapshot.type == Material.NOTE_BLOCK -> addInput(network, key) // Merge node behavior // block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) @@ -151,10 +153,12 @@ object PowerNodeFactory : NodeFactory() { } } - suspend fun addExtractor(network: ChunkPowerNetwork, key: BlockKey) { -// when () { -// -// } + fun addExtractor(network: ChunkPowerNetwork, position: BlockKey) { + network.nodes[position] = PowerExtractorNode(position) + } + + fun addInput(network: ChunkPowerNetwork, position: BlockKey) { + network.nodes[position] = PowerInputNode(position) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index dcb214c9a4..fd1980cafb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import org.bukkit.GameRule import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -125,9 +126,12 @@ class SolarPanelNode : MultiNode { * Returns the amount of power between ticks **/ fun getPower(network: ChunkPowerNetwork): Int { - val daylightMultiplier: Double = if (network.world.environment == World.Environment.NORMAL) { + val daylightMultiplier: Double = if ( + network.world.environment == World.Environment.NORMAL && + network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true + ) { val daylight = sin((network.world.time / (12000.0 / PI)) - (PI / 2)) - max(0.0, daylight) + max(0.0, daylight) * 1.5 // 1.5 to bring area under curve to around equal with night } else 0.5 val time = System.currentTimeMillis() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt deleted file mode 100644 index 4e7c540b76..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step - -import net.horizonsend.ion.server.features.transport.container.NamespacedResourceContainer -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode -import org.bukkit.block.BlockFace - -class PowerStep( - override val transportNetwork: ChunkPowerNetwork, - override val origin: NamespacedResourceContainer?, - direction: BlockFace, - currentNode: GridNode -) : Step(transportNetwork, origin, direction, currentNode) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index f3bbb9b716..e12a9ae0b9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -1,18 +1,13 @@ package net.horizonsend.ion.server.features.transport.step -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.container.ResourceContainer import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.GridNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.block.BlockFace abstract class Step( open val transportNetwork: ChunkTransportNetwork, open val origin: ResourceContainer<*>?, var direction: BlockFace, - var currentNode: GridNode ) { var status: TransferStatus = TransferStatus.STEPPING @@ -25,8 +20,6 @@ abstract class Step( if (depth >= MAX_STEP_DEPTH) return - debugAudience.highlightBlock(Vec3i(currentNode.x, currentNode.y, currentNode.z), 50L) - when (status) { TransferStatus.COMPLETE -> return TransferStatus.BLOCKED -> return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index e771ebcd0b..d59677a22d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -97,6 +97,7 @@ object NamespacedKeys { val NODE_COVERED_POSITIONS = key("node_covered_positions") val SOLAR_CELL_COUNT = key("solar_cell_count") val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") + val MULTIBLOCK_DESTINATIONS = key("multiblock_destinations") val NODE_TYPE = key("node_type") val NODES = key("chunk_power_nodes") From 2afde63e312d4a5918e3f4b5e3d5ec2013f0e9be Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 7 May 2024 00:31:34 -0500 Subject: [PATCH 040/500] test power multis --- .../server/features/multiblock/Multiblocks.kt | 6 ++ .../entity/PersistentMultiblockData.kt | 1 + .../entity/type/PoweredMultiblockEntity.kt | 5 +- .../powerbank/new/NewPowerBankMultiblock.kt | 84 +++++++++++++++++++ .../new/NewPowerBankMultiblockTier1.kt | 42 ++++++++++ .../new/NewPowerBankMultiblockTier2.kt | 42 ++++++++++ .../new/NewPowerBankMultiblockTier3.kt | 42 ++++++++++ 7 files changed, 218 insertions(+), 4 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index adf6cab8cc..a28881211e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -98,6 +98,9 @@ import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMu import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerCellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier3 @@ -326,6 +329,9 @@ object Multiblocks : IonServerComponent() { registerMultiblock(BargeReactorMultiBlock) registerMultiblock(OdometerMultiblock) registerMultiblock(TestMultiblock) + registerMultiblock(NewPowerBankMultiblockTier1) + registerMultiblock(NewPowerBankMultiblockTier2) + registerMultiblock(NewPowerBankMultiblockTier3) } private fun registerMultiblock(multiblock: Multiblock) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index 833c616ec9..991d2832b9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -29,6 +29,7 @@ class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Mul fun addAdditionalData(key: NamespacedKey, type: PersistentDataType<*, Z>, value: Z) = additionalData.set(key, type, value) fun getAdditionalData(key: NamespacedKey, type: PersistentDataType<*, Z>) = additionalData.get(key, type) + fun getAdditionalDataOrDefault(key: NamespacedKey, type: PersistentDataType<*, Z>, default: Z) = additionalData.getOrDefault(key, type, default) companion object : PersistentDataType { override fun getPrimitiveType() = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 9ebcf352e7..a791f1d186 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component @@ -12,9 +11,7 @@ import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { val position: BlockKey var powerUnsafe: Int - val type: PowerStoringMultiblock - - val maxPower get() = type.maxPower + val maxPower: Int fun setPower(amount: Int) { val correctedPower = amount.coerceIn(0, maxPower) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt new file mode 100644 index 0000000000..897af415d8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -0,0 +1,84 @@ +package net.horizonsend.ion.server.features.multiblock.type.powerbank.new + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace + +abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock { + abstract val tierMaterial: Material + override val name = "newpowerbank" + + override val signText = createSignText( + line1 = "&2Power &8Bank", + line2 = "&4------", + line3 = null, + line4 = tierText + ) + + override fun MultiblockShape.buildStructure() { + z(+0) { + y(-1) { + x(-1).extractor() + x(+0).wireInputComputer() + x(+1).extractor() + } + + y(+0) { + x(-1).anyGlassPane() + x(+0).anyGlass() + x(+1).anyGlassPane() + } + + y(+1) { + x(-1).anyGlassPane() + x(+0).anyGlass() + x(+1).anyGlassPane() + } + } + + z(+1) { + for (i in -1..1) { + y(i) { + x(-1).anyGlass() + x(+0).redstoneBlock() + x(+1).anyGlass() + } + } + } + + z(+2) { + y(-1) { + x(-1).type(tierMaterial) + x(+0).anyGlass() + x(+1).type(tierMaterial) + } + + y(+0) { + x(-1).anyGlassPane() + x(+0).anyGlass() + x(+1).anyGlassPane() + } + + y(+1) { + x(-1).anyGlassPane() + x(+0).anyGlass() + x(+1).anyGlassPane() + } + } + } + + abstract class PowerBankEntity( + multiblock: NewPowerBankMultiblock<*>, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override val maxPower: Int + ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt new file mode 100644 index 0000000000..0d29629c2f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt @@ -0,0 +1,42 @@ +package net.horizonsend.ion.server.features.multiblock.type.powerbank.new + +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType + +object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { + override val tierMaterial = Material.IRON_BLOCK + + override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier1Entity { + return NewPowerBankMultiblockTier1Entity( + this, + x, + y, + z, + world, + signOffset, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + ) + } + + class NewPowerBankMultiblockTier1Entity( + multiblock: NewPowerBankMultiblock<*>, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override var powerUnsafe: Int + ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 300_000) { + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, maxPower) + } + + override val position: BlockKey get() = toBlockKey(x, y, z) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt new file mode 100644 index 0000000000..214191c893 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt @@ -0,0 +1,42 @@ +package net.horizonsend.ion.server.features.multiblock.type.powerbank.new + +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType + +object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&eTier 2") { + override val tierMaterial = Material.GOLD_BLOCK + + override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier2Entity { + return NewPowerBankMultiblockTier2Entity( + this, + x, + y, + z, + world, + signOffset, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + ) + } + + class NewPowerBankMultiblockTier2Entity( + multiblock: NewPowerBankMultiblock<*>, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override var powerUnsafe: Int + ) : NewPowerBankMultiblock.PowerBankEntity(multiblock, x, y, z, world, signDirection, 350_000) { + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, maxPower) + } + + override val position: BlockKey get() = toBlockKey(x, y, z) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt new file mode 100644 index 0000000000..26b61c6415 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt @@ -0,0 +1,42 @@ +package net.horizonsend.ion.server.features.multiblock.type.powerbank.new + +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType + +object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock("&bTier 3") { + override val tierMaterial = Material.DIAMOND_BLOCK + + override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier3Entity { + return NewPowerBankMultiblockTier3Entity( + this, + x, + y, + z, + world, + signOffset, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + ) + } + + class NewPowerBankMultiblockTier3Entity( + multiblock: NewPowerBankMultiblock<*>, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override var powerUnsafe: Int + ) : NewPowerBankMultiblock.PowerBankEntity(multiblock, x, y, z, world, signDirection, 500_000) { + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, maxPower) + } + + override val position: BlockKey get() = toBlockKey(x, y, z) + } +} From 94fdae1035a70feb5d5535a1db2b410b124cebc9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 7 May 2024 02:52:17 -0500 Subject: [PATCH 041/500] preparation for power transfer --- .../server/command/admin/IonChunkCommand.kt | 31 ++++++++++ .../multiblock/ChunkMultiblockManager.kt | 8 +++ .../entity/type/PoweredMultiblockEntity.kt | 3 +- .../powerbank/new/NewPowerBankMultiblock.kt | 13 +++- .../new/NewPowerBankMultiblockTier1.kt | 3 - .../new/NewPowerBankMultiblockTier2.kt | 3 - .../new/NewPowerBankMultiblockTier3.kt | 5 +- .../transport/ChunkTransportManager.kt | 2 +- .../transport/grid/ChunkPowerNetwork.kt | 38 ++++++++++-- .../transport/grid/ChunkTransportNetwork.kt | 25 ++++---- .../features/transport/node/NodeFactory.kt | 4 +- .../features/transport/node/NodeType.kt | 9 ++- .../transport/node/power/EndRodNode.kt | 8 ++- .../node/power/PowerExtractorNode.kt | 2 +- .../transport/node/power/PowerInputNode.kt | 60 +++++++++++++++++-- .../transport/node/power/PowerNodeFactory.kt | 29 ++++----- .../transport/node/power/SolarPanelNode.kt | 36 +++++------ .../transport/node/power/SpongeNode.kt | 9 ++- .../transport/node/power/TransportNode.kt | 8 ++- .../features/transport/node/type/MultiNode.kt | 15 +++++ .../transport/node/type/SingleNode.kt | 16 +++++ .../ion/server/features/world/IonChunk.kt | 16 ++++- 22 files changed, 267 insertions(+), 76 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 925724fdd0..a128f8ce6c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.world.IonChunk.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text import org.bukkit.entity.Player @@ -101,4 +102,34 @@ object IonChunkCommand : SLCommand() { } } } + + @Subcommand("get node key") + fun getNode(sender: Player, key: Long, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { + val ionChunk = sender.chunk.ion() + + val grid = when (network) { + "power" -> ionChunk.transportNetwork.powerNetwork +// "item" -> ionChunk.transportNetwork.pipeGrid +// "gas" -> ionChunk.transportNetwork.gasGrid + else -> return@launch fail { "invalid network" } + } + + sender.information("Targeted node: ${grid.nodes[key]}") + } + + @Subcommand("get node look") + fun getNode(sender: Player, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { + val ionChunk = sender.chunk.ion() + val targeted = sender.getTargetBlock(null, 10) + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val grid = when (network) { + "power" -> ionChunk.transportNetwork.powerNetwork +// "item" -> ionChunk.transportNetwork.pipeGrid +// "gas" -> ionChunk.transportNetwork.gasGrid + else -> return@launch fail { "invalid network" } + } + + sender.information("Targeted node: ${grid.nodes[key]}") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index e2416f6d43..cbf9994d14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultibl import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.block.Sign @@ -167,5 +168,12 @@ class ChunkMultiblockManager(val chunk: IonChunk) { return multiblockEntities[key] } + /** + * Multiblock entities are stored on the block the sign is placed on + **/ + operator fun get(sign: Sign): MultiblockEntity? { + return multiblockEntities[getRelative(toBlockKey(sign.x, sign.y, sign.z), sign.getFacing().oppositeFace)] + } + fun isOccupied(x: Int, y: Int, z: Int): Boolean = multiblockEntities.containsKey(toBlockKey(x, y, z)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index a791f1d186..3189fca83a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { @@ -26,7 +25,7 @@ interface PoweredMultiblockEntity { /** * Returns the amount of power that could not be added **/ - fun addPower(sign: Sign, amount: Int): Int { + fun addPower(amount: Int): Int { val newAmount = getPower() + amount setPower(newAmount) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 897af415d8..20e88637b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -3,11 +3,14 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock { abstract val tierMaterial: Material @@ -80,5 +83,13 @@ abstract class NewPowerBankMultiblock world: World, signDirection: BlockFace, override val maxPower: Int - ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity + ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) + } + + override fun toString(): String { + return "POWER BANK TIER: $multiblock! Power: $powerUnsafe!!!" + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt index 0d29629c2f..d302afb135 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt @@ -33,9 +33,6 @@ object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock() override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT - override val nodeFactory: NodeFactory<*> = PowerNodeFactory + override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) + val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() override fun setup() { collectPowerMultiblockEntities() @@ -32,15 +37,36 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( createNodeFromBlock(new) }} - fun removeNode(key: Long) { - nodes.remove(key) + fun tickSolars() { + for ((key, solarPanel) in nodes.filterValuesIsInstance()) { + val power = solarPanel.getPower(this) + solarPanel.lastTicked = System.currentTimeMillis() + println("Solar panel generated $power power!") + + transferPower(solarPanel, power) + } } - val tickExecutor = IntervalExecutor(20) { + fun transferPower(start: TransportNode, amount: Int) { + var steps: Int = 0 + + var currentNode = start + + while (steps < 10) { + steps++ + if (currentNode is PowerInputNode) { + currentNode.multis.randomOrNull()?.addPower(amount) + + break + } + + currentNode = currentNode.transferableNeighbors.randomOrNull()?: break + } } override fun tick() { + tickSolars() // tickExecutor() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index 367d1d5b73..f485bd9244 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -27,12 +27,13 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val pdc get() = manager.chunk.inner.persistentDataContainer protected abstract val namespacedKey: NamespacedKey - protected abstract val nodeFactory: NodeFactory<*> + abstract val nodeFactory: NodeFactory<*> // val grids: Nothing = TODO("ChunkTransportNetwork system") init { loadData() + build() } open fun setup() {} @@ -43,7 +44,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { open suspend fun createNodeFromBlock(block: BlockSnapshot) { val key = toBlockKey(block.x, block.y, block.z) - nodeFactory.create(this, key, block) + nodeFactory.create(key, block) } abstract fun processBlockRemoval(key: Long) @@ -57,7 +58,9 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { // Deserialize once val nodeData = existing.get(NODES, PersistentDataType.TAG_CONTAINER_ARRAY)!!.map { TransportNode.fromPrimitive(it, pdc.adapterContext) } - nodeData.forEach { it.handlePlacement(this) } + nodeData.forEach { + it.handlePlacement(this) + } } fun save(adapterContext: PersistentDataAdapterContext) { @@ -87,8 +90,8 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { * Builds the transportNetwork TODO better documentation **/ fun build() = manager.scope.launch { - collectAllNodes().join() - collectNeighbors() +// collectAllNodes().join() + buildRelations() finalizeNodes() buildGraph() } @@ -133,8 +136,10 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { /** * Get the neighbors of a node **/ - private fun collectNeighbors() { -// nodes.values.forEach { node -> node.collectNeighbors() } + suspend fun buildRelations() { + for ((key, node) in nodes) { + node.buildRelations(this, key) + } } /** @@ -143,9 +148,9 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { * e.g. a straight section may be represented as a single node **/ private fun finalizeNodes() { - nodes.forEach { (_, node) -> - - } +// nodes.forEach { (_, node) -> +// +// } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index 57ab637971..bd0843555f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -4,9 +4,9 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -abstract class NodeFactory { +abstract class NodeFactory(val network: T) { /** * Create and handle placement of a node at the position, if one should be created **/ - abstract suspend fun create(network: @UnsafeVariance T, key: BlockKey, snapshot: BlockSnapshot) + abstract suspend fun create(key: BlockKey, snapshot: BlockSnapshot) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index d00b09774d..1b5c483d02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode @@ -8,11 +10,14 @@ import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.features.transport.node.power.TransportNode -enum class NodeType(val clazz: Class) { +enum class NodeType(val clazz: Class, val loadCallback: (TransportNode, ChunkTransportNetwork) -> Unit = { _, _ -> }) { //POWER SPONGE_NODE(SpongeNode::class.java), END_ROD_NODE(EndRodNode::class.java), - SOLAR_PANEL_NODE(SolarPanelNode::class.java), + SOLAR_PANEL_NODE(SolarPanelNode::class.java, { node, network -> + network as ChunkPowerNetwork + network.solarPanels.add(node as SolarPanelNode) + }), POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 84f30c8392..aa5e8e6c61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -38,7 +38,13 @@ class EndRodNode() : MultiNode { // Create new nodes, automatically merging together positions.forEach { - PowerNodeFactory.addEndRod(network as ChunkPowerNetwork, getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) + (network as ChunkPowerNetwork).nodeFactory.addEndRod(getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) } } + + override fun toString(): String = """ + EMD RPD NODE: + ${positions.size} positions, + Transferable to: ${transferableNeighbors.size} nodes + """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 9fd3a57f53..32504f88a8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -17,7 +17,7 @@ class PowerExtractorNode() : SingleNode { override val transferableNeighbors: MutableSet = ObjectOpenHashSet() override fun isTransferable(position: Long, node: TransportNode): Boolean { - TODO("Not yet implemented") + return node !is PowerInputNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index d77d9ce70c..ff052b308c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,11 +1,17 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_DESTINATIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates @@ -21,20 +27,62 @@ class PowerInputNode() : SingleNode { /** * Multiblocks that share this power input **/ - val multiblockPositions: MutableSet = LongOpenHashSet() + val multis: MutableSet = ObjectOpenHashSet() override fun isTransferable(position: Long, node: TransportNode): Boolean { - TODO("Not yet implemented") + return node is PowerExtractorNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - persistentDataContainer.set(MULTIBLOCK_DESTINATIONS, PersistentDataType.LONG_ARRAY, multiblockPositions.toLongArray()) } override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } + + override suspend fun buildRelations(network: ChunkTransportNetwork, position: BlockKey) { + super.buildRelations(network, position) + + network as ChunkPowerNetwork + + multis.clear() + multis.addAll(getPoweredMultiblocks(network)) + } - multiblockPositions.addAll(persistentDataContainer.getOrDefault(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, longArrayOf()).toList()) + private fun getPoweredMultiblocks(network: ChunkPowerNetwork): Iterable { + val x = getX(position) + val y = getY(position) + val z = getZ(position) + + return offsets.mapNotNull { offset -> + val newX = x + offset.x + val newY = y + offset.y + val newZ = z + offset.z + + val newKey = toBlockKey(newX, newY, newZ) + network.poweredMultiblockEntities[newKey] + } } + + companion object { + private val offsets = setOf( + // most multiblocks have the sign a block up and out of the computer + Vec3i(1, 1, 0), Vec3i(-1, 1, 0), Vec3i(0, 1, -1), Vec3i(0, 1, 1), + // power cells have it on the block + Vec3i(1, 0, 0), Vec3i(-1, 0, 0), Vec3i(0, 0, -1), Vec3i(0, 0, 1), + // drills have it on a corner + Vec3i(-1, 0, -1), Vec3i(1, 0, -1), Vec3i(1, 0, 1), Vec3i(-1, 0, 1), + // upside down mining lasers have signs below + Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), + // up and down + Vec3i(0, 1, 0), Vec3i(0, -1, 0) + ) + } + + override fun toString(): String = """ + POWER INPUT NODE: + ${multis.size} powered multiblocks, + Transferable to: ${transferableNeighbors.size} nodes + """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 204ff3447b..f178dd8a6c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -20,22 +20,22 @@ import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.data.Directional -object PowerNodeFactory : NodeFactory() { - override suspend fun create(network: ChunkPowerNetwork, key: BlockKey, snapshot: BlockSnapshot) { +class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory(network) { + override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { if (network.nodes.contains(key)) return when { // Straight wires - snapshot.type == Material.END_ROD -> addEndRod(network, snapshot.data as Directional, key) + snapshot.type == Material.END_ROD -> addEndRod(snapshot.data as Directional, key) // Omnidirectional wires - snapshot.type == Material.SPONGE -> addSponge(network, key) + snapshot.type == Material.SPONGE -> addSponge(key) // Extract power from storage snapshot.type == Material.CRAFTING_TABLE -> if (matchesSolarPanelStructure(network.world, key)) { - addSolarPanel(network, key) + addSolarPanel(key) } else { - addExtractor(network, key) + addExtractor(key) } // Check for extractor beneath @@ -43,7 +43,7 @@ object PowerNodeFactory : NodeFactory() { val extractorKey = getRelative(key, DOWN, 1) network.nodes.remove(extractorKey) if (matchesSolarPanelStructure(network.world, extractorKey)) { - addSolarPanel(network, extractorKey) + addSolarPanel(extractorKey) } } @@ -51,12 +51,12 @@ object PowerNodeFactory : NodeFactory() { val extractorKey = getRelative(key, DOWN, 2) network.nodes.remove(extractorKey) if (matchesSolarPanelStructure(network.world, extractorKey)) { - addSolarPanel(network, extractorKey) + addSolarPanel(extractorKey) } } // Add power to storage - snapshot.type == Material.NOTE_BLOCK -> addInput(network, key) + snapshot.type == Material.NOTE_BLOCK -> addInput(key) // Merge node behavior // block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) @@ -74,7 +74,7 @@ object PowerNodeFactory : NodeFactory() { } } - fun addSponge(network: ChunkPowerNetwork, position: BlockKey) { + fun addSponge(position: BlockKey) { val neighbors = getNeighborNodes(position, network.nodes).filterValuesIsInstance() when (neighbors.size) { @@ -111,7 +111,7 @@ object PowerNodeFactory : NodeFactory() { } } - suspend fun addEndRod(network: ChunkPowerNetwork, data: Directional, position: Long) { + suspend fun addEndRod(data: Directional, position: Long) { val axis = data.facing.axis // The neighbors in the direction of the wire's facing, that are also facing that direction @@ -153,18 +153,18 @@ object PowerNodeFactory : NodeFactory() { } } - fun addExtractor(network: ChunkPowerNetwork, position: BlockKey) { + fun addExtractor(position: BlockKey) { network.nodes[position] = PowerExtractorNode(position) } - fun addInput(network: ChunkPowerNetwork, position: BlockKey) { + fun addInput(position: BlockKey) { network.nodes[position] = PowerInputNode(position) } /** * Provided the key of the extractor, create or combine solar panel nodes **/ - suspend fun addSolarPanel(network: ChunkPowerNetwork, position: BlockKey) { + suspend fun addSolarPanel(position: BlockKey) { // The diamond and daylight detector val panelPositions = (1..2).map { getRelative(position, BlockFace.UP, it) } @@ -197,6 +197,7 @@ object PowerNodeFactory : NodeFactory() { // Add new position node.addPosition(network, position, panelPositions) + network.solarPanels += node } 1 -> { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index fd1980cafb..09723922be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -7,7 +7,6 @@ import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_COUNT import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -16,7 +15,6 @@ import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG_ARRAY import kotlin.math.PI import kotlin.math.max @@ -26,27 +24,25 @@ import kotlin.math.sin * Represents a solar panel, or multiple **/ class SolarPanelNode : MultiNode { - /** The number of solar cells contained in this node */ - var cellNumber: Int = 1 override val positions: MutableSet = LongOpenHashSet() /** The positions of extractors in this solar panel */ val extractorPositions = LongOpenHashSet() + /** The number of solar cells contained in this node */ + val cellNumber: Int get() = extractorPositions.size + override val transferableNeighbors: MutableSet = ObjectOpenHashSet() override fun isTransferable(position: Long, node: TransportNode): Boolean { - TODO("Not yet implemented") + return true } override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(SOLAR_CELL_COUNT, INTEGER, cellNumber) persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) persistentDataContainer.set(SOLAR_CELL_EXTRACTORS, LONG_ARRAY, extractorPositions.toLongArray()) } override fun loadData(persistentDataContainer: PersistentDataContainer) { - cellNumber = persistentDataContainer.getOrDefault(SOLAR_CELL_COUNT, INTEGER, 1) - val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, LONG_ARRAY) coveredPositions?.let { positions.addAll(it.asIterable()) } @@ -89,8 +85,6 @@ class SolarPanelNode : MultiNode { for (position: BlockKey in positions) { network.nodes[position] = this } - - cellNumber++ } fun removePosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { @@ -102,14 +96,15 @@ class SolarPanelNode : MultiNode { for (position: BlockKey in positions) { network.nodes.remove(position) } - - cellNumber-- } override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + network as ChunkPowerNetwork + network.solarPanels.remove(this) + // Create new nodes, automatically merging together extractorPositions.forEach { - PowerNodeFactory.addSolarPanel(network as ChunkPowerNetwork, it) + network.nodeFactory.addSolarPanel(it) } } @@ -117,10 +112,9 @@ class SolarPanelNode : MultiNode { super.drainTo(network, new) new.extractorPositions.addAll(extractorPositions) - new.cellNumber += cellNumber } - private var lastTicked: Long = System.currentTimeMillis() + var lastTicked: Long = System.currentTimeMillis() /** * Returns the amount of power between ticks @@ -137,7 +131,7 @@ class SolarPanelNode : MultiNode { val time = System.currentTimeMillis() val diff = time - this.lastTicked - return ((diff / 1000.0) * 5 * cellNumber * daylightMultiplier).toInt() + return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() } /** @@ -148,7 +142,7 @@ class SolarPanelNode : MultiNode { } companion object { - const val POWER_PER_SECOND = 50 + const val POWER_PER_SECOND = 5 suspend fun matchesSolarPanelStructure(world: World, key: BlockKey): Boolean { if (getBlockSnapshotAsync(world, key)?.type != Material.CRAFTING_TABLE) return false @@ -160,4 +154,12 @@ class SolarPanelNode : MultiNode { return getBlockSnapshotAsync(world, cell)?.type == Material.DAYLIGHT_DETECTOR } } + + override fun toString(): String = """ + SOLAR PANEL NODE: + ${positions.size} positions, + ${extractorPositions.size} extractor positions, + $cellNumber cells, + Transferable to: ${transferableNeighbors.size} nodes + """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 39f831c933..66b198b62b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -40,7 +40,14 @@ class SpongeNode() : MultiNode { override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { // Create new nodes, automatically merging together positions.forEach { - PowerNodeFactory.addSponge(network as ChunkPowerNetwork, it) + (network as ChunkPowerNetwork).nodeFactory.addSponge(it) } } + + override fun toString(): String = """ + SPONGE NODE: + ${positions.size} positions, + Transferable to: ${transferableNeighbors.size} nodes + """.trimIndent() + } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt index b64b3e1a12..662b2d8bc3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -45,7 +46,12 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 3edb5653ec..d1bc9249fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -3,7 +3,9 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative /** * A transport node that may cover many blocks to avoid making unnecessary steps @@ -62,4 +64,17 @@ interface MultiNode, T: MultiNode> : Transport network.nodes[key] = this } } + + override suspend fun buildRelations(network: ChunkTransportNetwork, position: BlockKey) { + for (offset in ADJACENT_BLOCK_FACES) { + val offsetKey = getRelative(position, offset, 1) + val neighborNode = network.nodes[offsetKey] ?: continue + + if (this == neighborNode) continue + + if (isTransferable(offsetKey, neighborNode)) { + transferableNeighbors.add(neighborNode) + } + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index f2005930d1..2e951758df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -2,6 +2,9 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative /** * A node that only occupies a single block @@ -12,4 +15,17 @@ interface SingleNode : TransportNode { override fun handlePlacement(network: ChunkTransportNetwork) { network.nodes[position] = this } + + override suspend fun buildRelations(network: ChunkTransportNetwork, position: BlockKey) { + for (offset in ADJACENT_BLOCK_FACES) { + val offsetKey = getRelative(position, offset, 1) + val neighborNode = network.nodes[offsetKey] ?: continue + + if (this == neighborNode) return + + if (isTransferable(offsetKey, neighborNode)) { + transferableNeighbors.add(neighborNode) + } + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt index 3be60b85d1..726059e9ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonChunk.kt @@ -6,10 +6,12 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.data.ChunkDataFixer import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.world.level.chunk.LevelChunkSection import org.bukkit.Chunk import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent @@ -73,6 +75,18 @@ class IonChunk(val inner: Chunk) { multiblockManager.tick() } + /** + * Gets the neighboring chunk in this direction + **/ + fun getNeighborIfLoaded(blockFace: BlockFace): IonChunk? { + require(CARDINAL_BLOCK_FACES.contains(blockFace)) + + val newX = x + blockFace.modX + val newZ = z + blockFace.modZ + + return get(world, newX, newZ) + } + companion object : SLEventListener() { @EventHandler fun onChunkLoad(event: ChunkLoadEvent) { @@ -128,7 +142,7 @@ class IonChunk(val inner: Chunk) { } /** - * Returns the chunk at the specified coordinates in the world if it is loaded + * Returns the chunk at the specified chunk coordinates in the world if it is loaded **/ operator fun get(world: World, x: Int, z: Int): IonChunk? { return world.ion.getChunk(x, z) From 4e0de6ff978f20e53e5e599c1d359d5a87231bc3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 7 May 2024 12:48:23 -0500 Subject: [PATCH 042/500] update signs (temp) --- .../multiblock/entity/MultiblockEntity.kt | 2 ++ .../entity/type/PoweredMultiblockEntity.kt | 26 ++++++++++++++++++- .../new/NewPowerBankMultiblockTier1.kt | 8 ++---- .../new/NewPowerBankMultiblockTier2.kt | 9 ++----- .../new/NewPowerBankMultiblockTier3.kt | 9 ++----- .../transport/grid/ChunkPowerNetwork.kt | 2 -- .../ion/server/miscellaneous/utils/Blocks.kt | 5 ++++ 7 files changed, 38 insertions(+), 23 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 0cdab7c432..c60739fbde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -33,6 +34,7 @@ abstract class MultiblockEntity( var signDirection: BlockFace ): PDCSerializable { override val type: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion + val position: BlockKey get() = toBlockKey(x, y, z) /** * Returns the origin of this multiblock as a Location diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 3189fca83a..8ceccd7657 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -1,10 +1,20 @@ package net.horizonsend.ion.server.features.multiblock.entity.type +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.front import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { @@ -16,6 +26,8 @@ interface PoweredMultiblockEntity { val correctedPower = amount.coerceIn(0, maxPower) powerUnsafe = correctedPower + + powerUpdateScope.launch { updatePowerVisually() } } fun getPower(): Int { @@ -59,11 +71,23 @@ interface PoweredMultiblockEntity { } companion object { - private val prefixComponent = Component.text("E: ", NamedTextColor.YELLOW) + private val prefixComponent = text("E: ", NamedTextColor.YELLOW) + private val powerUpdateScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) } /** Store power data */ fun storePower(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, powerUnsafe) } + + suspend fun updatePowerVisually() { + //TODO replace this + require(this is MultiblockEntity) + + val sign = getSign() ?: return + sign.front().line(2, formatPower()) + Tasks.sync { sign.update() } + } + + fun formatPower(): Component = ofChildren(prefixComponent, text(powerUnsafe, GREEN)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt index d302afb135..3969c0bbfb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt @@ -2,14 +2,12 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataType -object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { +data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { override val tierMaterial = Material.IRON_BLOCK override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier1Entity { @@ -32,8 +30,6 @@ object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&eTier 2") { +data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&eTier 2") { override val tierMaterial = Material.GOLD_BLOCK override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier2Entity { @@ -32,8 +30,5 @@ object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&bTier 3") { +data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock("&bTier 3") { override val tierMaterial = Material.DIAMOND_BLOCK override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier3Entity { @@ -32,8 +30,5 @@ object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock() -// val extractors = ConcurrentHashMap() override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) @@ -41,7 +40,6 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( for ((key, solarPanel) in nodes.filterValuesIsInstance()) { val power = solarPanel.getPower(this) solarPanel.lastTicked = System.currentTimeMillis() - println("Solar panel generated $power power!") transferPower(solarPanel, power) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index 237a7f3a3c..b0a8174e3f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -10,6 +10,8 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.WallSign +import org.bukkit.block.sign.Side +import org.bukkit.block.sign.SignSide import java.util.EnumSet /** @@ -135,3 +137,6 @@ fun BlockFace.matchesAxis(other: BlockFace) = this.axis == other.axis fun Sign.getFacing(): BlockFace = (this.blockData as? org.bukkit.block.data.type.Sign)?.rotation ?: (this.blockData as WallSign).facing + +fun Sign.front(): SignSide = getSide(Side.FRONT) +fun Sign.back(): SignSide = getSide(Side.BACK) From d58c61f83ad74cfd7866736ba406c8dd8a79b2ac Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 7 May 2024 12:50:31 -0500 Subject: [PATCH 043/500] rebuild relations too --- .../ion/server/features/transport/node/power/EndRodNode.kt | 2 ++ .../server/features/transport/node/power/SolarPanelNode.kt | 5 ++++- .../ion/server/features/transport/node/power/SpongeNode.kt | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index aa5e8e6c61..972e920f89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -35,9 +35,11 @@ class EndRodNode() : MultiNode { } override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + transferableNeighbors.clear() // Create new nodes, automatically merging together positions.forEach { + buildRelations(network, it) (network as ChunkPowerNetwork).nodeFactory.addEndRod(getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 09723922be..9f89cebc23 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -102,8 +102,11 @@ class SolarPanelNode : MultiNode { network as ChunkPowerNetwork network.solarPanels.remove(this) + transferableNeighbors.clear() + // Create new nodes, automatically merging together - extractorPositions.forEach { + positions.forEach { + buildRelations(network, it) network.nodeFactory.addSolarPanel(it) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 66b198b62b..fb2f818e14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -38,8 +38,11 @@ class SpongeNode() : MultiNode { } override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + transferableNeighbors.clear() + // Create new nodes, automatically merging together positions.forEach { + buildRelations(network, it) (network as ChunkPowerNetwork).nodeFactory.addSponge(it) } } From 7208373436b490da985ae5e5e359d26568ae6996 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 7 May 2024 13:29:46 -0500 Subject: [PATCH 044/500] rebuild relations when needed --- .../transport/grid/ChunkPowerNetwork.kt | 4 ++-- .../transport/grid/ChunkTransportNetwork.kt | 2 +- .../transport/node/power/EndRodNode.kt | 2 +- .../node/power/PowerExtractorNode.kt | 5 +++++ .../transport/node/power/PowerNodeFactory.kt | 22 +++++++++++++------ .../transport/node/power/SolarPanelNode.kt | 6 ++--- .../transport/node/power/SpongeNode.kt | 2 +- .../transport/node/power/TransportNode.kt | 7 +++++- .../features/transport/node/type/MultiNode.kt | 17 ++++++++++---- .../transport/node/type/SingleNode.kt | 6 ++++- 10 files changed, 52 insertions(+), 21 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index c4c3484d10..f7b9827af5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -36,7 +36,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( createNodeFromBlock(new) }} - fun tickSolars() { + private fun tickSolars() { for ((key, solarPanel) in nodes.filterValuesIsInstance()) { val power = solarPanel.getPower(this) solarPanel.lastTicked = System.currentTimeMillis() @@ -45,7 +45,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - fun transferPower(start: TransportNode, amount: Int) { + private fun transferPower(start: TransportNode, amount: Int) { //TODO remove this var steps: Int = 0 var currentNode = start diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index f485bd9244..cb2f44552d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -59,7 +59,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { // Deserialize once val nodeData = existing.get(NODES, PersistentDataType.TAG_CONTAINER_ARRAY)!!.map { TransportNode.fromPrimitive(it, pdc.adapterContext) } nodeData.forEach { - it.handlePlacement(this) + it.loadIntoNetwork(this) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 972e920f89..3944aef89a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -47,6 +47,6 @@ class EndRodNode() : MultiNode { override fun toString(): String = """ EMD RPD NODE: ${positions.size} positions, - Transferable to: ${transferableNeighbors.size} nodes + Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 32504f88a8..475254cec8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -27,5 +27,10 @@ class PowerExtractorNode() : SingleNode { override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } + + override fun toString(): String = """ + POWER INPUT NODE: + Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes + """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index f178dd8a6c..bc51b8cd15 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -74,13 +74,15 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory() when (neighbors.size) { // New sponge node 0 -> { - network.nodes[position] = SpongeNode(position) + network.nodes[position] = SpongeNode(position).apply { + onPlace(network, position) + } } // Consolidate into neighbor @@ -123,7 +125,9 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { - network.nodes[position] = EndRodNode(position) + network.nodes[position] = EndRodNode(position).apply { + onPlace(network, position) + } } 1 -> { @@ -153,12 +157,16 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { rebuildNode(network, position) } - fun addPosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { + suspend fun addPosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { extractorPositions += extractorKey addPosition(network, extractorKey) @@ -111,7 +111,7 @@ class SolarPanelNode : MultiNode { } } - override fun drainTo(network: ChunkTransportNetwork, new: SolarPanelNode) { + override suspend fun drainTo(network: ChunkTransportNetwork, new: SolarPanelNode) { super.drainTo(network, new) new.extractorPositions.addAll(extractorPositions) @@ -163,6 +163,6 @@ class SolarPanelNode : MultiNode { ${positions.size} positions, ${extractorPositions.size} extractor positions, $cellNumber cells, - Transferable to: ${transferableNeighbors.size} nodes + Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index fb2f818e14..a78d609103 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -50,7 +50,7 @@ class SpongeNode() : MultiNode { override fun toString(): String = """ SPONGE NODE: ${positions.size} positions, - Transferable to: ${transferableNeighbors.size} nodes + Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt index 662b2d8bc3..8cbac64f7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt @@ -39,7 +39,7 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index d1bc9249fd..f6d8717fee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -35,31 +35,35 @@ interface MultiNode, T: MultiNode> : Transport /** * Adds new a position to this node **/ - fun addPosition(network: ChunkTransportNetwork, position: BlockKey) { + suspend fun addPosition(network: ChunkTransportNetwork, position: BlockKey) { positions += position network.nodes[position] = this + + onPlace(network, position) } /** * Adds new a position to this node **/ - fun addPositions(network: ChunkTransportNetwork, newPositions: Iterable) { + suspend fun addPositions(network: ChunkTransportNetwork, newPositions: Iterable) { for (position in newPositions) { positions += position network.nodes[position] = this + + onPlace(network, position) } } /** * Drain all the positions and connections to the provided node **/ - fun drainTo(network: ChunkTransportNetwork, new: Self) { + suspend fun drainTo(network: ChunkTransportNetwork, new: Self) { new.transferableNeighbors.addAll(transferableNeighbors) new.addPositions(network, positions) } - override fun handlePlacement(network: ChunkTransportNetwork) { + override fun loadIntoNetwork(network: ChunkTransportNetwork) { for (key in positions) { network.nodes[key] = this } @@ -77,4 +81,9 @@ interface MultiNode, T: MultiNode> : Transport } } } + + override suspend fun onPlace(network: ChunkTransportNetwork, position: BlockKey) { + // Build relations for each position upon placement + buildRelations(network, position) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 2e951758df..759150fdb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative interface SingleNode : TransportNode { val position: Long - override fun handlePlacement(network: ChunkTransportNetwork) { + override fun loadIntoNetwork(network: ChunkTransportNetwork) { network.nodes[position] = this } @@ -28,4 +28,8 @@ interface SingleNode : TransportNode { } } } + + override suspend fun onPlace(network: ChunkTransportNetwork, position: BlockKey) { + buildRelations(network, position) + } } From 596fc24d042a12647840adec7344943c54715338 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 7 May 2024 13:51:22 -0500 Subject: [PATCH 045/500] update relations upon new multiblock creation --- .../multiblock/ChunkMultiblockManager.kt | 7 ++++++- .../server/features/multiblock/Multiblocks.kt | 7 ++----- .../transport/grid/ChunkPowerNetwork.kt | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index cbf9994d14..69b199b3ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonChunk @@ -65,7 +66,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { /** * Add a new multiblock to the chunk data **/ - fun addNewMultiblockEntity(multiblock: EntityMultiblock<*>, sign: Sign) { + suspend fun addNewMultiblockEntity(multiblock: EntityMultiblock<*>, sign: Sign) { // Allow smart cast multiblock as Multiblock @@ -87,6 +88,10 @@ class ChunkMultiblockManager(val chunk: IonChunk) { // Place the entity into the chunk addMultiblockEntity(entity) + + if (entity is PoweredMultiblockEntity) { + chunk.transportNetwork.powerNetwork.handleNewPoweredMultiblock(entity) + } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index a28881211e..450a0120f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -556,10 +556,7 @@ object Multiblocks : IonServerComponent() { ) sign.isWaxed = true - - Tasks.sync { - sign.update() - } + sign.update() if (multiblock is EntityMultiblock<*>) { // Multiblock entities are stored inside the block that the sign is placed on @@ -570,7 +567,7 @@ object Multiblocks : IonServerComponent() { val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - chunk.multiblockManager.addNewMultiblockEntity(multiblock, sign) + multiblockCoroutineScope.launch { chunk.multiblockManager.addNewMultiblockEntity(multiblock, sign) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index f7b9827af5..5b9f967175 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -2,17 +2,22 @@ package net.horizonsend.ion.server.features.transport.grid import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.filterValuesIsInstance import org.bukkit.NamespacedKey +import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { @@ -68,6 +73,19 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( // tickExecutor() } + /** + * Handle the addition of a new powered multiblock entity + **/ + suspend fun handleNewPoweredMultiblock(new: MultiblockEntity) { + // All directions + val neighboring = getNeighborNodes(new.position, nodes, BlockFace.entries) + .filterValues { it is PowerInputNode || it is PowerExtractorNode } + + neighboring.forEach { + it.value.buildRelations(this, getRelative(new.locationKey, it.key)) + } + } + private fun collectPowerMultiblockEntities() { manager.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> if (entity !is PoweredMultiblockEntity) return@forEach From 747f65cdcde9e9cc87682d81e40bd697c887577a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 8 May 2024 14:19:59 -0500 Subject: [PATCH 046/500] cleanup, remove node from itself when merging --- .../multiblock/entity/MultiblockEntity.kt | 2 +- .../transport/grid/ChunkPowerNetwork.kt | 26 +++++- .../transport/grid/ChunkTransportNetwork.kt | 17 +++- .../features/transport/node/NodeType.kt | 5 +- .../features/transport/node/NodeUtils.kt | 1 - .../node/{power => }/TransportNode.kt | 30 ++++--- .../transport/node/power/EndRodNode.kt | 14 ++-- .../node/power/PowerExtractorNode.kt | 29 ++++++- .../transport/node/power/PowerInputNode.kt | 9 ++- .../transport/node/power/PowerNodeFactory.kt | 39 ++++----- .../transport/node/power/SolarPanelNode.kt | 26 +++--- .../transport/node/power/SpongeNode.kt | 12 +-- .../features/transport/node/type/MultiNode.kt | 80 ++++++++++--------- .../transport/node/type/SingleNode.kt | 11 ++- .../persistence/NamespacedKeys.kt | 1 + .../persistence/PDCSerializable.kt | 6 +- 16 files changed, 189 insertions(+), 119 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{power => }/TransportNode.kt (78%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index c60739fbde..3040511312 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -33,7 +33,7 @@ abstract class MultiblockEntity( var world: World, var signDirection: BlockFace ): PDCSerializable { - override val type: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion + override val persistentDataType: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion val position: BlockKey get() = toBlockKey(x, y, z) /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt index 5b9f967175..815da3b3a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt @@ -6,12 +6,12 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -34,7 +34,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( override fun processBlockRemoval(key: Long) { manager.scope.launch { val previousNode = nodes[key] ?: return@launch - previousNode.handleRemoval(this@ChunkPowerNetwork, key) + previousNode.handleRemoval(key) }} override fun processBlockAddition(key: Long, new: BlockSnapshot) { manager.scope.launch { @@ -43,13 +43,26 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( private fun tickSolars() { for ((key, solarPanel) in nodes.filterValuesIsInstance()) { - val power = solarPanel.getPower(this) + val power = solarPanel.getPower() solarPanel.lastTicked = System.currentTimeMillis() transferPower(solarPanel, power) } } + private fun tickExtractors() { + for ((key, extractor) in extractors) { + extractor as PowerExtractorNode + if (!extractor.useful) continue + + val multis = extractor.extractableNodes.flatMap { it.multis } + + val power = multis.firstOrNull()?.removePower(1000) ?: continue + + transferPower(extractor, 1000 - power) + } + } + private fun transferPower(start: TransportNode, amount: Int) { //TODO remove this var steps: Int = 0 @@ -70,6 +83,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( override fun tick() { tickSolars() + tickExtractors() // tickExecutor() } @@ -82,7 +96,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( .filterValues { it is PowerInputNode || it is PowerExtractorNode } neighboring.forEach { - it.value.buildRelations(this, getRelative(new.locationKey, it.key)) + it.value.buildRelations(getRelative(new.locationKey, it.key)) } } @@ -93,4 +107,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( poweredMultiblockEntities[key] = entity } } + + companion object { + const val POWER_EXTRACTOR_STEP = 1000 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt index cb2f44552d..4de720155e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt @@ -3,11 +3,12 @@ package net.horizonsend.ion.server.features.transport.grid import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.NodeFactory -import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -57,9 +58,17 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val existing = pdc.get(POWER_TRANSPORT, PersistentDataType.TAG_CONTAINER) ?: return // Deserialize once - val nodeData = existing.get(NODES, PersistentDataType.TAG_CONTAINER_ARRAY)!!.map { TransportNode.fromPrimitive(it, pdc.adapterContext) } + val nodeData = existing.getOrDefault(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).mapNotNull { + runCatching { TransportNode.load(it, this) } + .onFailure { + IonServer.slF4JLogger.error("Error deserializing multiblock data! $it") + it.printStackTrace() + } + .getOrNull() + } + nodeData.forEach { - it.loadIntoNetwork(this) + it.loadIntoNetwork() } } @@ -138,7 +147,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { **/ suspend fun buildRelations() { for ((key, node) in nodes) { - node.buildRelations(this, key) + node.buildRelations(key) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 1b5c483d02..bc58b39619 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNo import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode -import net.horizonsend.ion.server.features.transport.node.power.TransportNode enum class NodeType(val clazz: Class, val loadCallback: (TransportNode, ChunkTransportNetwork) -> Unit = { _, _ -> }) { //POWER @@ -26,6 +25,10 @@ enum class NodeType(val clazz: Class, val loadCallback: (Tran //ITEM ; + fun newInstance(network: ChunkTransportNetwork): TransportNode { + return clazz.getDeclaredConstructor(network::class.java).newInstance(network) + } + fun newInstance(): TransportNode { return clazz.getDeclaredConstructor().newInstance() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index a40b9c8943..a1f7f657b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.transport.node.power.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt similarity index 78% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 8cbac64f7e..2bec497ade 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,8 +1,7 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -14,7 +13,8 @@ import org.bukkit.persistence.PersistentDataType * Represents a single node, or step, in transport transportNetwork **/ interface TransportNode : PDCSerializable { - override val type: Companion get() = Companion + val network: ChunkTransportNetwork + override val persistentDataType: Companion get() = Companion /** * The neighboring nodes that this node may transport to @@ -39,24 +39,24 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java @@ -73,14 +73,26 @@ interface TransportNode : PDCSerializable { - constructor(origin: Long) : this() { +class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode { + constructor(network: ChunkPowerNetwork, origin: Long) : this(network) { positions.add(origin) } @@ -34,18 +34,18 @@ class EndRodNode() : MultiNode { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } - override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun rebuildNode(position: BlockKey) { transferableNeighbors.clear() // Create new nodes, automatically merging together positions.forEach { - buildRelations(network, it) - (network as ChunkPowerNetwork).nodeFactory.addEndRod(getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) + buildRelations(it) + network.nodeFactory.addEndRod(getBlockSnapshotAsync(network.world, it)!!.data as Directional, it) } } override fun toString(): String = """ - EMD RPD NODE: + EMD ROD NODE: ${positions.size} positions, Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes """.trimIndent() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 475254cec8..fedd239684 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,21 +1,29 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerExtractorNode() : SingleNode { - constructor(position: BlockKey) : this() { +class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode { + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } override var position by Delegates.notNull() override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + val extractableNodes: MutableSet = ObjectOpenHashSet() + + val useful get() = extractableNodes.size >= 1 + override fun isTransferable(position: Long, node: TransportNode): Boolean { return node !is PowerInputNode } @@ -28,6 +36,23 @@ class PowerExtractorNode() : SingleNode { position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } + override suspend fun buildRelations(position: BlockKey) { + for (offset in ADJACENT_BLOCK_FACES) { + val offsetKey = getRelative(position, offset, 1) + val neighborNode = network.nodes[offsetKey] ?: continue + + if (this == neighborNode) return + + if (neighborNode is PowerInputNode) { + extractableNodes.add(neighborNode) + } + + if (isTransferable(offsetKey, neighborNode)) { + transferableNeighbors.add(neighborNode) + } + } + } + override fun toString(): String = """ POWER INPUT NODE: Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index ff052b308c..be6320e1b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -16,8 +17,8 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerInputNode() : SingleNode { - constructor(position: BlockKey) : this() { +class PowerInputNode(override val network: ChunkTransportNetwork) : SingleNode { + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -41,8 +42,8 @@ class PowerInputNode() : SingleNode { position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } - override suspend fun buildRelations(network: ChunkTransportNetwork, position: BlockKey) { - super.buildRelations(network, position) + override suspend fun buildRelations(position: BlockKey) { + super.buildRelations(position) network as ChunkPowerNetwork diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index bc51b8cd15..4b01872e88 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode.Companion.matchesSolarPanelStructure import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES @@ -80,15 +81,15 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { - network.nodes[position] = SpongeNode(position).apply { - onPlace(network, position) + network.nodes[position] = SpongeNode(network, position).apply { + onPlace(position) } } // Consolidate into neighbor 1 -> { val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - neighbor.addPosition(network, position) + neighbor.addPosition(position) } // Join multiple neighbors together @@ -102,11 +103,11 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory throw NotImplementedError() @@ -125,14 +126,14 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { - network.nodes[position] = EndRodNode(position).apply { - onPlace(network, position) + network.nodes[position] = EndRodNode(network, position).apply { + onPlace(position) } } 1 -> { val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - neighbor.addPosition(network, position) + neighbor.addPosition(position) } // Should be a max of 2 @@ -146,11 +147,11 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory throw IllegalArgumentException("Linear node had more than 2 neighbors") @@ -158,14 +159,14 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { - val node = SolarPanelNode() + val node = SolarPanelNode(network) // Add new position - node.addPosition(network, position, panelPositions) + node.addPosition(position, panelPositions) network.solarPanels += node } @@ -212,7 +213,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { @@ -222,11 +223,11 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory throw IllegalArgumentException() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 95c3b6ba40..76a18b8038 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS @@ -23,7 +23,7 @@ import kotlin.math.sin /** * Represents a solar panel, or multiple **/ -class SolarPanelNode : MultiNode { +class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { override val positions: MutableSet = LongOpenHashSet() /** The positions of extractors in this solar panel */ val extractorPositions = LongOpenHashSet() @@ -50,12 +50,11 @@ class SolarPanelNode : MultiNode { extractors?.let { extractorPositions.addAll(it.asIterable()) } } - override suspend fun handleRemoval(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun handleRemoval(position: BlockKey) { // Need to handle the extractor positions manually when { // Removed extractor, easier to find extractorPositions.contains(position) -> removePosition( - network as ChunkPowerNetwork, position, listOf(getRelative(position, BlockFace.UP, 1), getRelative(position, BlockFace.UP, 2)) ) @@ -67,19 +66,18 @@ class SolarPanelNode : MultiNode { } removePosition( - network as ChunkPowerNetwork, extractorPosition, listOf(getRelative(extractorPosition, BlockFace.UP, 1), getRelative(extractorPosition, BlockFace.UP, 2)) ) } } - rebuildNode(network, position) + rebuildNode(position) } - suspend fun addPosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { + suspend fun addPosition(extractorKey: BlockKey, others: Iterable) { extractorPositions += extractorKey - addPosition(network, extractorKey) + addPosition(extractorKey) positions += others for (position: BlockKey in positions) { @@ -87,7 +85,7 @@ class SolarPanelNode : MultiNode { } } - fun removePosition(network: ChunkPowerNetwork, extractorKey: BlockKey, others: Iterable) { + fun removePosition(extractorKey: BlockKey, others: Iterable) { extractorPositions -= extractorKey network.nodes.remove(extractorKey) positions.remove(extractorKey) @@ -98,7 +96,7 @@ class SolarPanelNode : MultiNode { } } - override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun rebuildNode(position: BlockKey) { network as ChunkPowerNetwork network.solarPanels.remove(this) @@ -106,13 +104,13 @@ class SolarPanelNode : MultiNode { // Create new nodes, automatically merging together positions.forEach { - buildRelations(network, it) + buildRelations(it) network.nodeFactory.addSolarPanel(it) } } - override suspend fun drainTo(network: ChunkTransportNetwork, new: SolarPanelNode) { - super.drainTo(network, new) + override suspend fun drainTo(new: SolarPanelNode) { + super.drainTo(new) new.extractorPositions.addAll(extractorPositions) } @@ -122,7 +120,7 @@ class SolarPanelNode : MultiNode { /** * Returns the amount of power between ticks **/ - fun getPower(network: ChunkPowerNetwork): Int { + fun getPower(): Int { val daylightMultiplier: Double = if ( network.world.environment == World.Environment.NORMAL && network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index a78d609103..b48333685c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -15,8 +15,8 @@ import org.bukkit.persistence.PersistentDataType * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode() : MultiNode { - constructor(origin: BlockKey) : this() { +class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode { + constructor(network: ChunkPowerNetwork, origin: BlockKey) : this(network) { positions.add(origin) } @@ -37,13 +37,13 @@ class SpongeNode() : MultiNode { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } - override suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun rebuildNode(position: BlockKey) { transferableNeighbors.clear() // Create new nodes, automatically merging together positions.forEach { - buildRelations(network, it) - (network as ChunkPowerNetwork).nodeFactory.addSponge(it) + buildRelations(it) + network.nodeFactory.addSponge(it) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index f6d8717fee..a4c19a504c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -10,66 +8,51 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative /** * A transport node that may cover many blocks to avoid making unnecessary steps **/ -interface MultiNode, T: MultiNode> : TransportNode { - /** - * The positions occupied by the node - **/ +interface MultiNode, Z: MultiNode> : TransportNode { + /** The positions occupied by the node **/ val positions: MutableSet - suspend fun rebuildNode(network: ChunkTransportNetwork, position: BlockKey) - - override suspend fun handleRemoval(network: ChunkTransportNetwork, position: BlockKey) { - network as ChunkPowerNetwork - - network.nodes.remove(position) - positions.remove(position) - - // Remove all - positions.forEach { - network.nodes.remove(it) - } - - rebuildNode(network, position) - } + /** + * Rebuild the node during the removal process + * + * When a position in a multi node is removed, the removed position is removed + * from the list of contained positions, and the node is rebuilt using this method. + **/ + suspend fun rebuildNode(position: BlockKey) /** * Adds new a position to this node **/ - suspend fun addPosition(network: ChunkTransportNetwork, position: BlockKey) { + suspend fun addPosition(position: BlockKey) { positions += position network.nodes[position] = this - onPlace(network, position) + onPlace(position) } /** - * Adds new a position to this node + * Adds multiple positions to this node **/ - suspend fun addPositions(network: ChunkTransportNetwork, newPositions: Iterable) { + suspend fun addPositions(newPositions: Iterable) { for (position in newPositions) { positions += position network.nodes[position] = this - onPlace(network, position) + onPlace(position) } } /** * Drain all the positions and connections to the provided node **/ - suspend fun drainTo(network: ChunkTransportNetwork, new: Self) { + suspend fun drainTo(new: Self) { + transferableNeighbors.remove(new) new.transferableNeighbors.addAll(transferableNeighbors) - new.addPositions(network, positions) - } - - override fun loadIntoNetwork(network: ChunkTransportNetwork) { - for (key in positions) { - network.nodes[key] = this - } + new.addPositions(positions) } - override suspend fun buildRelations(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) val neighborNode = network.nodes[offsetKey] ?: continue @@ -82,8 +65,29 @@ interface MultiNode, T: MultiNode> : Transport } } - override suspend fun onPlace(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun handleRemoval(position: BlockKey) { + // Remove the position from the network + network.nodes.remove(position) + // Remove the position from this node + positions.remove(position) + + // Remove all positions + positions.forEach { + network.nodes.remove(it) + } + + // Rebuild the node without the lost position + rebuildNode(position) + } + + override suspend fun onPlace(position: BlockKey) { // Build relations for each position upon placement - buildRelations(network, position) + buildRelations(position) + } + + override fun loadIntoNetwork() { + for (key in positions) { + network.nodes[key] = this + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 759150fdb5..1fa8f81eb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.power.TransportNode +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -12,11 +11,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative interface SingleNode : TransportNode { val position: Long - override fun loadIntoNetwork(network: ChunkTransportNetwork) { + override fun loadIntoNetwork() { network.nodes[position] = this } - override suspend fun buildRelations(network: ChunkTransportNetwork, position: BlockKey) { + override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) val neighborNode = network.nodes[offsetKey] ?: continue @@ -29,7 +28,7 @@ interface SingleNode : TransportNode { } } - override suspend fun onPlace(network: ChunkTransportNetwork, position: BlockKey) { - buildRelations(network, position) + override suspend fun onPlace(position: BlockKey) { + buildRelations(position) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index d59677a22d..ff45f605ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -99,6 +99,7 @@ object NamespacedKeys { val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") val MULTIBLOCK_DESTINATIONS = key("multiblock_destinations") val NODE_TYPE = key("node_type") + val NODE_ORIGIN = key("node_origin") val NODES = key("chunk_power_nodes") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt index ff7b51179c..a56f921173 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializable.kt @@ -6,13 +6,13 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType interface PDCSerializable > { - val type: T + val persistentDataType: T fun serialize(adapterContext: PersistentDataAdapterContext, data: V): PersistentDataContainer { - return type.toPrimitive(data, adapterContext) + return persistentDataType.toPrimitive(data, adapterContext) } fun store(destination: PersistentDataContainer, key: NamespacedKey, data: V) { - destination.set(key, type, data) + destination.set(key, persistentDataType, data) } } From 3f081ae2ee14195aeba321e76e46d7a5b1dee80c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 8 May 2024 14:25:28 -0500 Subject: [PATCH 047/500] transfer check cleanup --- .../server/features/transport/node/TransportNode.kt | 2 +- .../server/features/transport/node/power/EndRodNode.kt | 5 +++-- .../transport/node/power/PowerExtractorNode.kt | 10 ++++++---- .../features/transport/node/power/PowerInputNode.kt | 2 +- .../features/transport/node/power/SolarPanelNode.kt | 6 ++++-- .../server/features/transport/node/power/SpongeNode.kt | 5 +++-- .../server/features/transport/node/type/MultiNode.kt | 2 +- .../server/features/transport/node/type/SingleNode.kt | 2 +- .../server/features/transport/node/type/SourceNode.kt | 8 ++++++++ 9 files changed, 28 insertions(+), 14 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 2bec497ade..24279abf1b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -24,7 +24,7 @@ interface TransportNode : PDCSerializable = ObjectOpenHashSet() - override fun isTransferable(position: Long, node: TransportNode): Boolean { - return true + override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + return node !is SourceNode } override fun loadData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index fedd239684..7726ff5406 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -12,7 +13,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode { +class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, SourceNode { constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -24,8 +25,9 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode { val useful get() = extractableNodes.size >= 1 - override fun isTransferable(position: Long, node: TransportNode): Boolean { - return node !is PowerInputNode + override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + if (node is PowerInputNode) return false + return node !is SourceNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { @@ -47,7 +49,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode { extractableNodes.add(neighborNode) } - if (isTransferable(offsetKey, neighborNode)) { + if (isTransferableTo(offsetKey, neighborNode)) { transferableNeighbors.add(neighborNode) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index be6320e1b1..b7df18cfe2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -30,7 +30,7 @@ class PowerInputNode(override val network: ChunkTransportNetwork) : SingleNode { **/ val multis: MutableSet = ObjectOpenHashSet() - override fun isTransferable(position: Long, node: TransportNode): Boolean { + override fun isTransferableTo(position: Long, node: TransportNode): Boolean { return node is PowerExtractorNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 76a18b8038..58b97e88c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -23,7 +24,7 @@ import kotlin.math.sin /** * Represents a solar panel, or multiple **/ -class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { +class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, SourceNode { override val positions: MutableSet = LongOpenHashSet() /** The positions of extractors in this solar panel */ val extractorPositions = LongOpenHashSet() @@ -33,7 +34,8 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() - override fun isTransferable(position: Long, node: TransportNode): Boolean { + override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + // Solar panels should be able to transfer through extractors and other solar panels return true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index b48333685c..b2a8fff574 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer @@ -24,8 +25,8 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() - override fun isTransferable(position: BlockKey, node: TransportNode): Boolean { - return true + override fun isTransferableTo(position: BlockKey, node: TransportNode): Boolean { + return node !is SourceNode } override fun loadData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index a4c19a504c..94db89f890 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -59,7 +59,7 @@ interface MultiNode, Z: MultiNode> : Transport if (this == neighborNode) continue - if (isTransferable(offsetKey, neighborNode)) { + if (isTransferableTo(offsetKey, neighborNode)) { transferableNeighbors.add(neighborNode) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 1fa8f81eb5..9df3813d07 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -22,7 +22,7 @@ interface SingleNode : TransportNode { if (this == neighborNode) return - if (isTransferable(offsetKey, neighborNode)) { + if (isTransferableTo(offsetKey, neighborNode)) { transferableNeighbors.add(neighborNode) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt new file mode 100644 index 0000000000..a2417ccdcc --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.transport.node.type + +/** + * Representing the start of a power system + * + * Nodes may not transfer into a source node + **/ +interface SourceNode From 15f45690be9673cc47f5eea2763259d936abddbc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 9 May 2024 01:02:20 -0500 Subject: [PATCH 048/500] working power transfer --- .../server/features/machine/PowerMachines.kt | 6 +- .../entity/type/PoweredMultiblockEntity.kt | 1 + .../multiblock/util/AsyncBlockUtils.kt | 14 ++-- .../transport/ChunkTransportManager.kt | 2 +- .../{grid => network}/ChunkPowerNetwork.kt | 60 +++++++++++++---- .../ChunkTransportNetwork.kt | 7 +- .../features/transport/node/NodeFactory.kt | 2 +- .../features/transport/node/NodeType.kt | 4 +- .../features/transport/node/TransportNode.kt | 11 +++- .../transport/node/power/EndRodNode.kt | 23 ++++++- .../node/power/PowerEqualSplitterNode.kt | 5 ++ .../node/power/PowerExtractorNode.kt | 30 ++++++++- .../transport/node/power/PowerInputNode.kt | 47 ++++++++++++- .../transport/node/power/PowerNodeFactory.kt | 2 +- .../transport/node/power/SolarPanelNode.kt | 44 +++++++++++-- .../transport/node/power/SpongeNode.kt | 23 ++++++- .../features/transport/node/type/MultiNode.kt | 3 + .../server/features/transport/step/Step.kt | 66 +++++++------------ 18 files changed, 261 insertions(+), 89 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{grid => network}/ChunkPowerNetwork.kt (65%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{grid => network}/ChunkTransportNetwork.kt (94%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt index 72c64ee750..852e2668cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt @@ -11,7 +11,6 @@ import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.block.Sign -import org.bukkit.block.sign.Side import org.bukkit.inventory.FurnaceRecipe import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType @@ -73,9 +72,8 @@ object PowerMachines : IonServerComponent() { if (!sign.persistentDataContainer.has(NamespacedKeys.MULTIBLOCK)) return power sign.persistentDataContainer.set(NamespacedKeys.POWER, PersistentDataType.INTEGER, correctedPower) - sign.getSide(Side.FRONT).line(2, Component.text().append(prefixComponent, Component.text(correctedPower, NamedTextColor.GREEN)).build()) - sign.update(false, false) - +// sign.getSide(Side.FRONT).line(2, Component.text().append(prefixComponent, Component.text(correctedPower, NamedTextColor.GREEN)).build()) +// sign.update(false, false) return power } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 8ceccd7657..18948dec46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -27,6 +27,7 @@ interface PoweredMultiblockEntity { powerUnsafe = correctedPower + //TODO better solution powerUpdateScope.launch { updatePowerVisually() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index 581393765f..79d796aa9d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -26,6 +26,7 @@ import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockState import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers +import java.lang.reflect.Method /** * X and Z in real coordinates @@ -99,15 +100,16 @@ suspend fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlock return blockState } -fun createBlockState(world: World, blockPos: BlockPos, data: BlockData, tileEntity: BlockEntity?): CraftBlockState { - val getFactoryForMaterial = CraftBlockStates::class.java.getDeclaredMethod("getFactory", Material::class.java) - getFactoryForMaterial.isAccessible = true +val getFactoryForMaterial: Method = CraftBlockStates::class.java.getDeclaredMethod("getFactory", Material::class.java).apply { + isAccessible = true +} +fun createBlockState(world: World, blockPos: BlockPos, data: BlockData, tileEntity: BlockEntity?): CraftBlockState { val material = CraftMagicNumbers.getMaterial((data as CraftBlockData).state.block) val factory = getFactoryForMaterial.invoke(null, material) - val method = factory::class.java.getDeclaredMethod( + val blockStateFactory = factory::class.java.getDeclaredMethod( "createBlockState", World::class.javaObjectType, BlockPos::class.javaObjectType, @@ -115,7 +117,7 @@ fun createBlockState(world: World, blockPos: BlockPos, data: BlockData, tileEnti BlockEntity::class.javaObjectType ) - method.isAccessible = true + blockStateFactory.isAccessible = true - return method.invoke(factory, world, blockPos, data.state, tileEntity) as CraftBlockState + return blockStateFactory.invoke(factory, world, blockPos, data.state, tileEntity) as CraftBlockState } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 1c42b1bce3..4c617d1a75 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt similarity index 65% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index 815da3b3a9..03408fcb65 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -1,7 +1,8 @@ -package net.horizonsend.ion.server.features.transport.grid +package net.horizonsend.ion.server.features.transport.network import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.coroutines.launch +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot @@ -12,6 +13,7 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNo import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.step.PowerOriginStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -19,6 +21,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.filterValuesIsInstance import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.atomic.AtomicInteger +import kotlin.math.min class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { val poweredMultiblockEntities = ConcurrentHashMap() @@ -41,25 +45,41 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( createNodeFromBlock(new) }} - private fun tickSolars() { - for ((key, solarPanel) in nodes.filterValuesIsInstance()) { - val power = solarPanel.getPower() - solarPanel.lastTicked = System.currentTimeMillis() + private suspend fun tickSolars() { + for (solarPanel in nodes.filterValuesIsInstance().values.distinct()) { + val power = solarPanel.tickAndGetPower() + println("Ticking solar 1") - transferPower(solarPanel, power) + if (power <= 0) continue + println("Ticking solar 2") + + println("Starting solar ticking") + + runCatching { solarPanel.handleStep(PowerOriginStep(AtomicInteger(), solarPanel, power)) }.onFailure { + IonServer.slF4JLogger.error("Exception ticking solar panel! $it") + it.printStackTrace() + } } } - private fun tickExtractors() { - for ((key, extractor) in extractors) { - extractor as PowerExtractorNode + private suspend fun tickExtractors() { + if (extractors.isNotEmpty()) println("Ticking extractors") + + for ((_, extractor) in extractors) { + println("Ticking extractor 1") if (!extractor.useful) continue + println("Ticking extractor 2") - val multis = extractor.extractableNodes.flatMap { it.multis } + val extractablePowerPool = extractor.extractableNodes.flatMap { it.multis } + val sum = extractablePowerPool.sumOf { it.getPower() } + val extractablePower = min(sum, POWER_EXTRACTOR_STEP) - val power = multis.firstOrNull()?.removePower(1000) ?: continue + println("Starting step extractor") - transferPower(extractor, 1000 - power) + runCatching { extractor.handleStep(PowerOriginStep(AtomicInteger(), extractor, extractablePower)) }.onFailure { + IonServer.slF4JLogger.error("Exception ticking extractor! $it") + it.printStackTrace() + } } } @@ -81,7 +101,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - override fun tick() { + override suspend fun tick() { tickSolars() tickExtractors() // tickExecutor() @@ -108,7 +128,21 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } + /** + * Find a destination by stepping along transferable nodes and following their rules + **/ + fun findDestination(origin: TransportNode) { + var steps = 1 + var current: TransportNode = origin + + while (steps < MAX_DEPTH) { + + steps++ + } + } + companion object { const val POWER_EXTRACTOR_STEP = 1000 + const val MAX_DEPTH = 200 } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index 4de720155e..0eae9e248e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.grid +package net.horizonsend.ion.server.features.transport.network import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -21,7 +22,7 @@ import java.util.concurrent.ConcurrentHashMap abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val nodes: ConcurrentHashMap = ConcurrentHashMap() - val extractors: ConcurrentHashMap = ConcurrentHashMap() + val extractors: ConcurrentHashMap = ConcurrentHashMap() val world get() = manager.chunk.world @@ -93,7 +94,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { /** * **/ - abstract fun tick() + abstract suspend fun tick() /** * Builds the transportNetwork TODO better documentation diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index bd0843555f..39046752eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey abstract class NodeFactory(val network: T) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index bc58b39619..a26bf5404f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 24279abf1b..cc68ac3144 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,7 +1,8 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -58,6 +59,14 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 68f873febc..05d5982cad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -3,10 +3,12 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.data.Directional @@ -36,8 +38,6 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode() @@ -38,6 +43,11 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } + override fun loadIntoNetwork() { + super.loadIntoNetwork() + network.extractors[position] = this + } + override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) @@ -55,8 +65,24 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, } } + override suspend fun handleStep(step: Step) { + // Nothing can transfer to extractors + if (step is TransportStep) { + println("Extractor location: ${toVec3i(position)}, ${network.world}") + println("========\nPower extractor step received step $step\n==========") + } + + step as PowerOriginStep + + val next = transferableNeighbors.randomOrNull() ?: return + + // Simply move on to the next node + TransportStep(step, step.steps, next, step).invoke() + } + + override fun toString(): String = """ - POWER INPUT NODE: + POWER Extractor NODE: Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index b7df18cfe2..afd57eaffe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -2,10 +2,11 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -15,9 +16,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import kotlin.math.floor +import kotlin.math.min import kotlin.properties.Delegates -class PowerInputNode(override val network: ChunkTransportNetwork) : SingleNode { +class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -66,6 +69,44 @@ class PowerInputNode(override val network: ChunkTransportNetwork) : SingleNode { } } + override suspend fun handleStep(step: Step) { + // This is not an origin node, so we can assume that it is not an origin step + step as TransportStep + + val origin = step.origin + val multi = multis.randomOrNull() ?: return + + val share = floor(origin.power * step.share).toInt() + + origin.power -= share + + multi.addPower(share) + + var remaining = share + + if (origin.currentNode is PowerExtractorNode) { + for (extractable in origin.currentNode.extractableNodes.flatMap { it.multis }) { + val toTake = min(remaining, extractable.getPower()) + + remaining -= toTake + extractable.removePower(toTake) + + if (remaining <= 0) break + } + } + + println(""" + + Reached multiblock input + Origin: $origin + + Selected $multi + Added $share to $multi + Remaining origin power: ${origin.power} + + """.trimIndent()) + } + companion object { private val offsets = setOf( // most multiblocks have the sign a block up and out of the computer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 4b01872e88..9267f768ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 58b97e88c2..426e055909 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -3,10 +3,13 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.PowerOriginStep +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -36,7 +39,7 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { + val previousNode = step.previous.currentNode + val availableNeighbors = transferableNeighbors.filterNot { it == previousNode } + val next = availableNeighbors.randomOrNull() ?: return + + // Simply move on to the next node + TransportStep( + step.origin, + step.steps, + next, + step + ).invoke() + } + + is PowerOriginStep -> { + val next = transferableNeighbors.randomOrNull() ?: return + + // Simply move on to the next node + TransportStep(step, step.steps, next, step).invoke() + } + + else -> throw NotImplementedError("Unrecognized step type $step") + } + } + companion object { const val POWER_PER_SECOND = 5 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index b2a8fff574..1c318e34d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -2,10 +2,12 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer @@ -39,8 +41,6 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode, Z: MultiNode> : Transport network.nodes.remove(it) } + // Rebuild relations after cleared + transferableNeighbors.clear() + // Rebuild the node without the lost position rebuildNode(position) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index e12a9ae0b9..1f17a6220d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -1,51 +1,35 @@ package net.horizonsend.ion.server.features.transport.step -import net.horizonsend.ion.server.features.transport.container.ResourceContainer -import net.horizonsend.ion.server.features.transport.grid.ChunkTransportNetwork -import org.bukkit.block.BlockFace +import net.horizonsend.ion.server.features.transport.node.TransportNode +import java.util.concurrent.atomic.AtomicInteger -abstract class Step( - open val transportNetwork: ChunkTransportNetwork, - open val origin: ResourceContainer<*>?, - var direction: BlockFace, -) { - var status: TransferStatus = TransferStatus.STEPPING +interface Step { + val steps: AtomicInteger + val currentNode: TransportNode + val share: Float - var children = mutableSetOf() + suspend operator fun invoke() { + if (steps.incrementAndGet() > MAX_DEPTH) return - var depth: Int = 0 - - fun step() { - depth++ - - if (depth >= MAX_STEP_DEPTH) return - - when (status) { - TransferStatus.COMPLETE -> return - TransferStatus.BLOCKED -> return - TransferStatus.SPLIT -> stepChildren() - TransferStatus.STEPPING -> step() - } - } - - private fun stepChildren() { - val iterator = children.iterator() - - while (iterator.hasNext()) { - val child = iterator.next() - - // Remove finished children - if (child.status == TransferStatus.COMPLETE || child.status == TransferStatus.BLOCKED) { - iterator.remove() - - continue - } - - child.step() - } + currentNode.handleStep(this) } companion object { - const val MAX_STEP_DEPTH = 25 + const val MAX_DEPTH = 200 } } + +data class PowerOriginStep( + override val steps: AtomicInteger, + override val currentNode: TransportNode, + var power: Int, + override val share: Float = 1f +) : Step + +data class TransportStep( + val origin: PowerOriginStep, + override val steps: AtomicInteger, + override val currentNode: TransportNode, + val previous: Step, + override val share: Float = 1f +) : Step From 1813316b67b206222fb93303a2bc54f9fc56f8fc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 9 May 2024 01:48:21 -0500 Subject: [PATCH 049/500] new relationship system --- .../transport/network/ChunkPowerNetwork.kt | 18 ----- .../transport/node/NodeRelationship.kt | 71 +++++++++++++++++++ .../features/transport/node/TransportNode.kt | 20 +++++- .../transport/node/power/EndRodNode.kt | 12 ++-- .../node/power/PowerExtractorNode.kt | 18 ++--- .../transport/node/power/PowerInputNode.kt | 9 ++- .../transport/node/power/SolarPanelNode.kt | 13 ++-- .../transport/node/power/SpongeNode.kt | 13 ++-- .../features/transport/node/type/MultiNode.kt | 10 +-- .../transport/node/type/SingleNode.kt | 5 +- 10 files changed, 130 insertions(+), 59 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index 03408fcb65..a0da758e8c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -83,24 +83,6 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - private fun transferPower(start: TransportNode, amount: Int) { //TODO remove this - var steps: Int = 0 - - var currentNode = start - - while (steps < 10) { - steps++ - - if (currentNode is PowerInputNode) { - currentNode.multis.randomOrNull()?.addPower(amount) - - break - } - - currentNode = currentNode.transferableNeighbors.randomOrNull()?: break - } - } - override suspend fun tick() { tickSolars() tickExtractors() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt new file mode 100644 index 0000000000..d1bf5fca7b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -0,0 +1,71 @@ +package net.horizonsend.ion.server.features.transport.node + +/** + * This class represents a relationship between two nodes + * The information contains whether they may transfer to / from each other, from each side + **/ +class NodeRelationship( + val sideOne: RelationSide, + val sideTwo: RelationSide +) { + /** + * A side on a node relationship + * + * @param node The node on this side of the relationship + * @param transferAllowed Whether this node is allowed to transfer to the other side + **/ + class RelationSide(val node: TransportNode, val transferAllowed: Boolean) + + /** + * Break the relation between the two nodes + **/ + fun breakUp() { + sideOne.node.relationships.remove(this) + sideTwo.node.relationships.remove(this) + } + + /** + * If by some occurrence a node has entered into a relationship with itself, remove that relation + **/ + fun removeSelfRelation() { + if (sideOne.node == sideTwo.node) { + breakUp() + } + } + + /** + * Replace one side of the relationship with a new one + * + * This will clear relations to the previous node and add relations to the new one + **/ + fun replaceSide(replacedSide: TransportNode, newPartner: TransportNode) { + breakUp() + + // Find which side is being replaced + when (replacedSide) { + sideOne.node -> { + val new = create(newPartner, sideTwo.node) ?: return + sideTwo.node.relationships.add(new) + } + sideTwo.node -> { + val new = create(newPartner, sideOne.node) ?: return + sideOne.node.relationships.add(new) + } + else -> throw IllegalArgumentException("Cannot replace node that is not present in relationship") + } + } + + companion object { + fun create(nodeOne: TransportNode, nodeTwo: TransportNode): NodeRelationship? { + val canTransferTo = nodeOne.isTransferableTo(nodeTwo) + val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) + + // Do not add the relationship if neither side can transfer + if (!canTransferFrom && !canTransferTo) return null + + return NodeRelationship(RelationSide(nodeOne, canTransferTo), RelationSide(nodeTwo, canTransferFrom),) + } + } +} + + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index cc68ac3144..2be7680846 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -18,14 +18,28 @@ interface TransportNode : PDCSerializable + val relationships: MutableSet + + /** + * Break all relations between this node and others + **/ + fun clearRelations() { + relationships.forEach { it.breakUp() } + } + + fun addRelationship(other: TransportNode) { + // Null if relationship was not worth it + val relationship = NodeRelationship.create(this, other) ?: return + + relationships.add(relationship) + } /** * Returns whether this node may transport to the provided node **/ - fun isTransferableTo(position: Long, node: TransportNode): Boolean + fun isTransferableTo(node: TransportNode): Boolean /** * Store additional required data in the serialized container diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 05d5982cad..0331884727 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode @@ -21,10 +22,9 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode = LongOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() - override val transferableNeighbors: MutableSet = ObjectOpenHashSet() - - override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + override fun isTransferableTo(node: TransportNode): Boolean { return node !is SourceNode } @@ -50,8 +50,8 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode() + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this } - override var position by Delegates.notNull() - override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() val extractableNodes: MutableSet = ObjectOpenHashSet() val useful get() = extractableNodes.size >= 1 - override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + override fun isTransferableTo(node: TransportNode): Boolean { if (node is PowerInputNode) return false return node !is SourceNode } @@ -59,9 +62,8 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, extractableNodes.add(neighborNode) } - if (isTransferableTo(offsetKey, neighborNode)) { - transferableNeighbors.add(neighborNode) - } + // Add a relationship, if one should be added + addRelationship(neighborNode) } } @@ -74,7 +76,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, step as PowerOriginStep - val next = transferableNeighbors.randomOrNull() ?: return + val next = relationships.randomOrNull()?.sideTwo?.node ?: return // Simply move on to the next node TransportStep(step, step.steps, next, step).invoke() @@ -83,7 +85,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, override fun toString(): String = """ POWER Extractor NODE: - Transferable to: ${transferableNeighbors.joinToString { it.javaClass.simpleName }} nodes + Transferable to: ${relationships.joinToString { it.sideTwo.node.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index afd57eaffe..049e71fb3e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.step.Step @@ -26,14 +27,14 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { } override var position by Delegates.notNull() - override val transferableNeighbors: MutableSet = ObjectOpenHashSet() /** * Multiblocks that share this power input **/ val multis: MutableSet = ObjectOpenHashSet() - override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + override val relationships: MutableSet = ObjectOpenHashSet() + override fun isTransferableTo(node: TransportNode): Boolean { return node is PowerExtractorNode } @@ -48,8 +49,6 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { override suspend fun buildRelations(position: BlockKey) { super.buildRelations(position) - network as ChunkPowerNetwork - multis.clear() multis.addAll(getPoweredMultiblocks(network)) } @@ -125,6 +124,6 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { override fun toString(): String = """ POWER INPUT NODE: ${multis.size} powered multiblocks, - Transferable to: ${transferableNeighbors.size} nodes + Transferable to: ${relationships.joinToString { it.sideTwo.node.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 426e055909..7bb7a929be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode @@ -35,9 +36,9 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() - override fun isTransferableTo(position: Long, node: TransportNode): Boolean { + override fun isTransferableTo(node: TransportNode): Boolean { // Solar panels should be able to transfer through extractors and other solar panels return node !is PowerExtractorNode } @@ -155,8 +156,8 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { val previousNode = step.previous.currentNode - val availableNeighbors = transferableNeighbors.filterNot { it == previousNode } - val next = availableNeighbors.randomOrNull() ?: return + val availableNeighbors = relationships.filterNot { it.sideTwo.node == previousNode } + val next = availableNeighbors.randomOrNull()?.sideTwo?.node ?: return // Simply move on to the next node TransportStep( @@ -168,7 +169,7 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { - val next = transferableNeighbors.randomOrNull() ?: return + val next = relationships.randomOrNull()?.sideTwo?.node ?: return // Simply move on to the next node TransportStep(step, step.steps, next, step).invoke() @@ -197,6 +198,6 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode = LongOpenHashSet() - override val transferableNeighbors: MutableSet = ObjectOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() - override fun isTransferableTo(position: BlockKey, node: TransportNode): Boolean { + override fun isTransferableTo(node: TransportNode): Boolean { return node !is SourceNode } @@ -53,8 +54,8 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode, Z: MultiNode> : Transport * Drain all the positions and connections to the provided node **/ suspend fun drainTo(new: Self) { - transferableNeighbors.remove(new) - new.transferableNeighbors.addAll(transferableNeighbors) + relationships.forEach { it.replaceSide(this, new) } + new.relationships.forEach { it.removeSelfRelation() } new.addPositions(positions) } @@ -59,8 +59,8 @@ interface MultiNode, Z: MultiNode> : Transport if (this == neighborNode) continue - if (isTransferableTo(offsetKey, neighborNode)) { - transferableNeighbors.add(neighborNode) + if (isTransferableTo(neighborNode)) { + addRelationship(neighborNode) } } } @@ -77,7 +77,7 @@ interface MultiNode, Z: MultiNode> : Transport } // Rebuild relations after cleared - transferableNeighbors.clear() + clearRelations() // Rebuild the node without the lost position rebuildNode(position) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 9df3813d07..17432bba04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -22,9 +22,8 @@ interface SingleNode : TransportNode { if (this == neighborNode) return - if (isTransferableTo(offsetKey, neighborNode)) { - transferableNeighbors.add(neighborNode) - } + // Add a relationship, if one should be added + addRelationship(neighborNode) } } From 0ae36ada9ce2807a9289f50a8133a8270918b08b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 9 May 2024 01:54:50 -0500 Subject: [PATCH 050/500] turn up power tick rate for testing --- .../ion/server/features/transport/ChunkTransportManager.kt | 2 +- .../ion/server/features/transport/node/power/PowerInputNode.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 4c617d1a75..ef3b1feee8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -34,7 +34,7 @@ class ChunkTransportManager( // gasGrid.setup() } - val tickExecutor = IntervalExecutor(40) { scope.launch { + val tickExecutor = IntervalExecutor(5) { scope.launch { powerNetwork.tick() }} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 049e71fb3e..6876e8b094 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -124,6 +124,6 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { override fun toString(): String = """ POWER INPUT NODE: ${multis.size} powered multiblocks, - Transferable to: ${relationships.joinToString { it.sideTwo.node.javaClass.simpleName }} nodes + Transferable to: ${relationships.joinToString { if (it.sideTwo.transferAllowed) { it.sideTwo.node.javaClass.simpleName } else "" }} nodes """.trimIndent() } From bbecada3b4ababa23124283f8cc9b463d9e4573b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 9 May 2024 13:36:02 -0500 Subject: [PATCH 051/500] cleaning, bug fixes --- .../transport/network/ChunkPowerNetwork.kt | 15 ++++--------- .../transport/node/NodeRelationship.kt | 4 ++-- .../features/transport/node/TransportNode.kt | 15 +++++++++++++ .../transport/node/power/EndRodNode.kt | 20 ++++++++++------- .../node/power/PowerExtractorNode.kt | 11 ++++++---- .../transport/node/power/PowerInputNode.kt | 22 +++++++++---------- .../transport/node/power/SolarPanelNode.kt | 8 ++++--- .../transport/node/power/SpongeNode.kt | 7 ++---- .../features/transport/node/type/MultiNode.kt | 4 +--- .../transport/node/type/SingleNode.kt | 4 ++++ 10 files changed, 63 insertions(+), 47 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index a0da758e8c..ed70f783bc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -29,6 +29,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) + + /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() override fun setup() { @@ -38,6 +40,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( override fun processBlockRemoval(key: Long) { manager.scope.launch { val previousNode = nodes[key] ?: return@launch + extractors.remove(key) + previousNode.handleRemoval(key) }} @@ -48,12 +52,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( private suspend fun tickSolars() { for (solarPanel in nodes.filterValuesIsInstance().values.distinct()) { val power = solarPanel.tickAndGetPower() - println("Ticking solar 1") if (power <= 0) continue - println("Ticking solar 2") - - println("Starting solar ticking") runCatching { solarPanel.handleStep(PowerOriginStep(AtomicInteger(), solarPanel, power)) }.onFailure { IonServer.slF4JLogger.error("Exception ticking solar panel! $it") @@ -63,21 +63,14 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } private suspend fun tickExtractors() { - if (extractors.isNotEmpty()) println("Ticking extractors") - for ((_, extractor) in extractors) { - println("Ticking extractor 1") if (!extractor.useful) continue - println("Ticking extractor 2") val extractablePowerPool = extractor.extractableNodes.flatMap { it.multis } val sum = extractablePowerPool.sumOf { it.getPower() } val extractablePower = min(sum, POWER_EXTRACTOR_STEP) - println("Starting step extractor") - runCatching { extractor.handleStep(PowerOriginStep(AtomicInteger(), extractor, extractablePower)) }.onFailure { - IonServer.slF4JLogger.error("Exception ticking extractor! $it") it.printStackTrace() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index d1bf5fca7b..ebb72381a8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -4,7 +4,7 @@ package net.horizonsend.ion.server.features.transport.node * This class represents a relationship between two nodes * The information contains whether they may transfer to / from each other, from each side **/ -class NodeRelationship( +data class NodeRelationship( val sideOne: RelationSide, val sideTwo: RelationSide ) { @@ -14,7 +14,7 @@ class NodeRelationship( * @param node The node on this side of the relationship * @param transferAllowed Whether this node is allowed to transfer to the other side **/ - class RelationSide(val node: TransportNode, val transferAllowed: Boolean) + data class RelationSide(val node: TransportNode, val transferAllowed: Boolean) /** * Break the relation between the two nodes diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 2be7680846..fbe51635b5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -29,11 +29,20 @@ interface TransportNode : PDCSerializable = relationships.filter { + // That this node can transfer to the other + it.sideOne.transferAllowed + }.map { it.sideTwo.node } + /** * Store additional required data in the serialized container **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 0331884727..3b09709484 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -38,11 +38,16 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() - - val extractableNodes: MutableSet = ObjectOpenHashSet() + val extractableNodes: MutableSet get() = getTransferableNodes().mapNotNullTo(mutableSetOf()) { it as? PowerInputNode } val useful get() = extractableNodes.size >= 1 @@ -51,6 +50,11 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, network.extractors[position] = this } + override suspend fun handleRemoval(position: BlockKey) { + network.extractors.remove(position) + super.handleRemoval(position) + } + override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) @@ -82,10 +86,9 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, TransportStep(step, step.steps, next, step).invoke() } - override fun toString(): String = """ POWER Extractor NODE: - Transferable to: ${relationships.joinToString { it.sideTwo.node.javaClass.simpleName }} nodes + Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 6876e8b094..7c38221a1f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -94,16 +94,16 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { } } - println(""" - - Reached multiblock input - Origin: $origin - - Selected $multi - Added $share to $multi - Remaining origin power: ${origin.power} - - """.trimIndent()) +// println(""" +// +// Reached multiblock input +// Origin: $origin +// +// Selected $multi +// Added $share to $multi +// Remaining origin power: ${origin.power} +// +// """.trimIndent()) } companion object { @@ -124,6 +124,6 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { override fun toString(): String = """ POWER INPUT NODE: ${multis.size} powered multiblocks, - Transferable to: ${relationships.joinToString { if (it.sideTwo.transferAllowed) { it.sideTwo.node.javaClass.simpleName } else "" }} nodes + Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes """.trimIndent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 7bb7a929be..b4529f7c41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -83,6 +83,9 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode) { extractorPositions += extractorKey + + // Make sure there isn't still an extractor + network.extractors.remove(extractorKey) addPosition(extractorKey) positions += others @@ -156,8 +159,7 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { val previousNode = step.previous.currentNode - val availableNeighbors = relationships.filterNot { it.sideTwo.node == previousNode } - val next = availableNeighbors.randomOrNull()?.sideTwo?.node ?: return + val next = getTransferableNodes().filterNot { it == previousNode }.randomOrNull() ?: return // Simply move on to the next node TransportStep( @@ -198,6 +200,6 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, Z: MultiNode> : Transport if (this == neighborNode) continue - if (isTransferableTo(neighborNode)) { - addRelationship(neighborNode) - } + addRelationship(neighborNode) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 17432bba04..30eff9d858 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -30,4 +30,8 @@ interface SingleNode : TransportNode { override suspend fun onPlace(position: BlockKey) { buildRelations(position) } + + override suspend fun handleRemoval(position: BlockKey) { + network.nodes.remove(position) + } } From b0ed7bc21a269807fd4ebb099f689bc809fc1d53 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 10 May 2024 02:53:23 -0500 Subject: [PATCH 052/500] cleaning --- .../transport/ChunkTransportManager.kt | 4 +- .../network/ChunkTransportNetwork.kt | 24 ++-- .../transport/node/NodeRelationship.kt | 52 +++----- .../features/transport/node/NodeType.kt | 8 +- .../features/transport/node/NodeUtils.kt | 29 ++++- .../features/transport/node/TransportNode.kt | 18 ++- .../transport/node/power/EndRodNode.kt | 1 - .../node/power/PowerExtractorNode.kt | 6 - .../transport/node/power/PowerInputNode.kt | 6 +- .../transport/node/power/PowerNodeFactory.kt | 120 +++++------------- .../transport/node/power/SolarPanelNode.kt | 20 +-- .../transport/node/power/SpongeNode.kt | 16 +-- .../features/transport/node/type/MultiNode.kt | 23 +++- .../transport/node/type/SingleNode.kt | 1 + .../server/miscellaneous/utils/Collections.kt | 13 +- 15 files changed, 147 insertions(+), 194 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index ef3b1feee8..ce6e78eaaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -24,10 +24,12 @@ class ChunkTransportManager( val extractorData = getExtractorData(chunk.inner) - val powerNetwork = ChunkPowerNetwork(this) + val powerNetwork = ChunkPowerNetwork(this).apply { loadData(); build() } // val pipeGrid = ChunkPowerNetwork(this) // TODO // val gasGrid = ChunkPowerNetwork(this) // TODO + + fun setup() { powerNetwork.setup() // pipeGrid.setup() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index 0eae9e248e..a8e6c1a137 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -33,11 +33,6 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { // val grids: Nothing = TODO("ChunkTransportNetwork system") - init { - loadData() - build() - } - open fun setup() {} /** @@ -55,22 +50,21 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { /** * Load stored node data from the chunk **/ - private fun loadData() { + fun loadData() { val existing = pdc.get(POWER_TRANSPORT, PersistentDataType.TAG_CONTAINER) ?: return // Deserialize once val nodeData = existing.getOrDefault(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).mapNotNull { - runCatching { TransportNode.load(it, this) } - .onFailure { - IonServer.slF4JLogger.error("Error deserializing multiblock data! $it") - it.printStackTrace() - } - .getOrNull() + runCatching { TransportNode.load(it, this) }.onFailure { + IonServer.slF4JLogger.error("Error deserializing multiblock data! $it") + it.printStackTrace() + }.getOrNull() } - nodeData.forEach { - it.loadIntoNetwork() - } + nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { + IonServer.slF4JLogger.error("Error loading node into network!") + it.printStackTrace() + } } } fun save(adapterContext: PersistentDataAdapterContext) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index ebb72381a8..680347c83b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -20,50 +20,30 @@ data class NodeRelationship( * Break the relation between the two nodes **/ fun breakUp() { - sideOne.node.relationships.remove(this) - sideTwo.node.relationships.remove(this) - } - - /** - * If by some occurrence a node has entered into a relationship with itself, remove that relation - **/ - fun removeSelfRelation() { - if (sideOne.node == sideTwo.node) { - breakUp() - } - } - - /** - * Replace one side of the relationship with a new one - * - * This will clear relations to the previous node and add relations to the new one - **/ - fun replaceSide(replacedSide: TransportNode, newPartner: TransportNode) { - breakUp() - - // Find which side is being replaced - when (replacedSide) { - sideOne.node -> { - val new = create(newPartner, sideTwo.node) ?: return - sideTwo.node.relationships.add(new) - } - sideTwo.node -> { - val new = create(newPartner, sideOne.node) ?: return - sideOne.node.relationships.add(new) - } - else -> throw IllegalArgumentException("Cannot replace node that is not present in relationship") - } + println("Removing ${sideOne.node}'s relation to ${sideTwo.node}") + sideOne.node.removeRelationship(sideTwo.node) + println("Removing ${sideTwo.node}'s relation to ${sideOne.node}") + sideTwo.node.removeRelationship(sideOne.node) } companion object { - fun create(nodeOne: TransportNode, nodeTwo: TransportNode): NodeRelationship? { + fun create(nodeOne: TransportNode, nodeTwo: TransportNode) { + println("Attempting to create relationship between $nodeOne and $nodeTwo") + Throwable().printStackTrace() + val canTransferTo = nodeOne.isTransferableTo(nodeTwo) val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) + println("Node one can transfer to node two: $canTransferTo") + println("Node two can transfer to node one: $canTransferFrom") + // Do not add the relationship if neither side can transfer - if (!canTransferFrom && !canTransferTo) return null + if (!canTransferFrom && !canTransferTo) return - return NodeRelationship(RelationSide(nodeOne, canTransferTo), RelationSide(nodeTwo, canTransferFrom),) + println("Adding a relation between $nodeOne and $nodeTwo") + nodeOne.relationships += NodeRelationship(RelationSide(nodeOne, canTransferTo), RelationSide(nodeTwo, canTransferFrom)) + println("Adding a relation between $nodeTwo and $nodeOne") + nodeTwo.relationships += NodeRelationship(RelationSide(nodeTwo, canTransferFrom), RelationSide(nodeOne, canTransferTo)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index a26bf5404f..d67aa8839b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode @@ -9,14 +8,11 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode -enum class NodeType(val clazz: Class, val loadCallback: (TransportNode, ChunkTransportNetwork) -> Unit = { _, _ -> }) { +enum class NodeType(val clazz: Class) { //POWER SPONGE_NODE(SpongeNode::class.java), END_ROD_NODE(EndRodNode::class.java), - SOLAR_PANEL_NODE(SolarPanelNode::class.java, { node, network -> - network as ChunkPowerNetwork - network.solarPanels.add(node as SolarPanelNode) - }), + SOLAR_PANEL_NODE(SolarPanelNode::class.java), POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index a1f7f657b4..de04243a0b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,14 +1,17 @@ package net.horizonsend.ion.server.features.transport.node +import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull import org.bukkit.block.BlockFace -fun getNeighborNodes(position: Long, nodes: Map, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { +fun getNeighborNodes(position: BlockKey, nodes: Map, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { val x = getX(position) val y = getY(position) val z = getZ(position) @@ -16,10 +19,32 @@ fun getNeighborNodes(position: Long, nodes: Map, checkFaces nodes[toBlockKey(x + it.modX, y + it.modY, z + it.modZ)] } -fun getNeighborNodes(position: Long, nodes: Collection, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.mapNotNull { +fun getNeighborNodes(position: BlockKey, nodes: Collection, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.mapNotNull { val x = getX(position) val y = getY(position) val z = getZ(position) toBlockKey(x + it.modX, y + it.modY, z + it.modZ).takeIf { key -> nodes.contains(key) } } + +inline fun getMatchingNeighborNodes(position: BlockKey, nodes: Map): MutableList = + getNeighborNodes(position, nodes).values.filterIsInstanceTo>(mutableListOf()) + +/** + * Merge the provided nodes into the largest node [by position] in the collection + * + * @return the node that the provided were merged into + **/ +suspend fun > handleMerges(neighbors: MutableCollection): Self { + // Get the largest neighbor + val largestNeighbor = neighbors.popMaxByOrNull { + it.positions.size + } ?: throw ConcurrentModificationException("Node removed during processing") + + // Merge all other connected nodes into the largest + neighbors.forEach { + it.drainTo(largestNeighbor) + } + + return largestNeighbor +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index fbe51635b5..7d8c27597d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -26,7 +26,10 @@ interface TransportNode : PDCSerializable() + suspend fun addSponge(position: BlockKey, handleRelationships: Boolean = true) { + val neighbors = getNeighborNodes(position, network.nodes).values.filterIsInstanceTo>(mutableListOf()) - when (neighbors.size) { + val finalNode = when (neighbors.size) { // New sponge node - 0 -> { - network.nodes[position] = SpongeNode(network, position).apply { - onPlace(position) - } - } + 0 -> SpongeNode(network, position).apply { loadIntoNetwork() } // Consolidate into neighbor - 1 -> { - val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - neighbor.addPosition(position) - } + 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") // Join multiple neighbors together - in 2..6 -> { - // Get the larger - val spongeNeighbors: MutableMap = mutableMapOf() - neighbors.mapNotNullTo(spongeNeighbors) { (key, value) -> (value as? SpongeNode)?.let { key to value } } - - // Get the largest neighbor - val largestNeighbor = spongeNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: throw ConcurrentModificationException("Node removed during processing") - - // Merge all other connected nodes into the largest - spongeNeighbors.forEach { - it.value.drainTo(largestNeighbor) - } - - // Add this node - largestNeighbor.addPosition(position) - } + in 2..6 -> handleMerges(neighbors).addPosition(position) else -> throw NotImplementedError() } + + if (handleRelationships) finalNode.rebuildRelations() } - suspend fun addEndRod(data: Directional, position: Long) { + suspend fun addEndRod(data: Directional, position: Long, handleRelationships: Boolean = true) { val axis = data.facing.axis // The neighbors in the direction of the wire's facing, that are also facing that direction val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()).filterKeys { val relative = getRelative(position, it) (getBlockSnapshotAsync(network.world, relative, false)?.data as? Directional)?.facing?.axis == axis - }.filterValuesIsInstance() + }.values.filterIsInstanceTo>(mutableListOf()) - when (neighbors.size) { + val finalNode = when (neighbors.size) { // Disconnected - 0 -> { - network.nodes[position] = EndRodNode(network, position).apply { - onPlace(position) - } - } + 0 -> EndRodNode(network, position).apply { loadIntoNetwork() } - 1 -> { - val neighbor = neighbors.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") - neighbor.addPosition(position) - } + // Consolidate into neighbor + 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") // Should be a max of 2 - 2 -> { - // Get the larger - val wireNeighbors: MutableMap = mutableMapOf() - neighbors.mapNotNullTo(wireNeighbors) { (key, value) -> (value as? EndRodNode)?.let { key to value } } - - // Get the largest neighbor - val largestNeighbor = wireNeighbors.popMaxByOrNull { it.value.positions.size }?.value ?: throw ConcurrentModificationException("Node removed during processing") - - // Merge all other connected nodes into the largest - wireNeighbors.forEach { - it.value.drainTo(largestNeighbor) - } - - // Add this node - largestNeighbor.addPosition(position) - } + 2 -> handleMerges(neighbors).addPosition(position) else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") } + + if (handleRelationships) finalNode.rebuildRelations() } suspend fun addExtractor(position: BlockKey) { @@ -173,7 +130,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory + val neighboringNodes = CARDINAL_BLOCK_FACES.mapNotNullTo(mutableListOf()) { direction -> val relativeSide = getRelative(position, direction) (-1..3).firstNotNullOfOrNull { @@ -198,39 +155,20 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { - val node = SolarPanelNode(network) - - // Add new position - node.addPosition(position, panelPositions) - network.solarPanels += node - } - - 1 -> { - val neighbor = neighboringNodes.values.firstOrNull() ?: throw ConcurrentModificationException("Node removed during processing") + } - // Add new position to neighbor - neighbor.addPosition(position, panelPositions) - } + val node = when (neighboringNodes.size) { + 0 -> SolarPanelNode(network).apply { + network.solarPanels += this + }.addPosition(position, panelPositions) - in 2..4 -> { - val largestNeighbor = neighboringNodes - .popMaxByOrNull { it.value.positions.size } - ?.value ?: throw ConcurrentModificationException("Node removed during processing") + 1 -> neighboringNodes.firstOrNull()?.addPosition(position, panelPositions) ?: throw ConcurrentModificationException("Node removed during processing") - // Merge all other connected nodes into the largest - neighboringNodes.forEach { - it.value.drainTo(largestNeighbor) - } - - // Add this node - largestNeighbor.addPosition(position, panelPositions) - } + in 2..4 -> handleMerges(neighboringNodes).addPosition(position, panelPositions) else -> throw IllegalArgumentException() } + + if (handleRelationships) node.rebuildRelations() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index b4529f7c41..4e810248c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -81,7 +81,7 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode) { + suspend fun addPosition(extractorKey: BlockKey, others: Iterable): SolarPanelNode { extractorPositions += extractorKey // Make sure there isn't still an extractor @@ -92,6 +92,8 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode) { @@ -171,7 +173,7 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { - val next = relationships.randomOrNull()?.sideTwo?.node ?: return + val next = getTransferableNodes().randomOrNull() ?: return // Simply move on to the next node TransportStep(step, step.steps, next, step).invoke() @@ -181,6 +183,11 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, Z: MultiNode> : Transport /** * Adds new a position to this node **/ - suspend fun addPosition(position: BlockKey) { + suspend fun addPosition(position: BlockKey): Self { positions += position network.nodes[position] = this onPlace(position) + + @Suppress("UNCHECKED_CAST") + return this as Self } /** @@ -46,10 +49,11 @@ interface MultiNode, Z: MultiNode> : Transport * Drain all the positions and connections to the provided node **/ suspend fun drainTo(new: Self) { - relationships.forEach { it.replaceSide(this, new) } + clearRelations() + new.clearRelations() - new.relationships.forEach { it.removeSelfRelation() } new.addPositions(positions) + new.positions.forEach { new.buildRelations(it) } } override suspend fun buildRelations(position: BlockKey) { @@ -63,6 +67,14 @@ interface MultiNode, Z: MultiNode> : Transport } } + suspend fun rebuildRelations() { + clearRelations() + + positions.forEach { + buildRelations(it) + } + } + override suspend fun handleRemoval(position: BlockKey) { // Remove the position from the network network.nodes.remove(position) @@ -81,10 +93,7 @@ interface MultiNode, Z: MultiNode> : Transport rebuildNode(position) } - override suspend fun onPlace(position: BlockKey) { - // Build relations for each position upon placement - buildRelations(position) - } + override suspend fun onPlace(position: BlockKey) {} override fun loadIntoNetwork() { for (key in positions) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 30eff9d858..8119ab95ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -33,5 +33,6 @@ interface SingleNode : TransportNode { override suspend fun handleRemoval(position: BlockKey) { network.nodes.remove(position) + clearRelations() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index fcad572846..4190fef8cb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -4,6 +4,7 @@ import com.google.common.collect.Multimap import com.google.common.collect.MultimapBuilder import com.google.common.collect.Table import net.horizonsend.ion.common.utils.miscellaneous.randomInt +import org.checkerframework.checker.units.qual.K import java.util.EnumSet import java.util.concurrent.ThreadLocalRandom import kotlin.random.Random @@ -51,7 +52,10 @@ fun Collection>.toMap(): Map { fun List.safeSubList(fromIndex: Int, toIndex: Int): List = this.subList(fromIndex.coerceAtLeast(this.size), toIndex.coerceAtMost(this.size)) fun Map.mapTo(other: MutableMap, transform: (Map.Entry) -> Pair) = other.putAll(map(transform)) -fun Map.mapNotNullTo(other: MutableMap, transform: (Map.Entry) -> Pair?) = other.putAll(map(transform).filterNotNull()) +fun Map.mapNotNullTo(destination: MutableMap, transform: (Map.Entry) -> Pair?): MutableMap = destination.apply { + putAll(map(transform).filterNotNull()) +} + fun MutableSet.and(vararg others: T): MutableSet = apply { others.forEach { add(it) } } fun Iterable.filterIsInstance(clazz: KClass, transform: (T) -> Any?): List { @@ -103,6 +107,13 @@ fun > MutableMap.popMaxByOrNull(selector: (Map.Ent return max } +fun > MutableCollection.popMaxByOrNull(selector: (V) -> R): V? { + val max = maxByOrNull(selector) ?: return null + remove(max) + + return max +} + inline fun Iterable.associateWithNotNull(valueSelector: (K) -> V?): Map { @Suppress("UNCHECKED_CAST") return associateWith(valueSelector).filterValues { it != null } as Map From f431238254fed4b5041b5bc0bbd7a3772d83cacc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 10 May 2024 02:55:06 -0500 Subject: [PATCH 053/500] apply fixes to other nodes --- .../server/features/transport/node/power/EndRodNode.kt | 10 +++++----- .../features/transport/node/power/SolarPanelNode.kt | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index f8feec566d..fe4a9496cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -38,15 +38,15 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode Date: Fri, 10 May 2024 13:41:18 -0500 Subject: [PATCH 054/500] power transport work, remove some debug --- .../server/command/admin/IonChunkCommand.kt | 25 +++++++++++++++++++ .../transport/ChunkTransportManager.kt | 2 +- .../transport/network/ChunkPowerNetwork.kt | 14 ----------- .../transport/node/NodeRelationship.kt | 8 ------ .../features/transport/node/TransportNode.kt | 1 - .../transport/node/power/EndRodNode.kt | 14 +++++------ .../node/power/PowerExtractorNode.kt | 6 +++-- .../transport/node/power/PowerInputNode.kt | 2 ++ .../transport/node/power/SolarPanelNode.kt | 5 ++-- .../transport/node/power/SpongeNode.kt | 7 ++++-- .../server/features/transport/step/Step.kt | 18 +++++++++++-- 11 files changed, 63 insertions(+), 39 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index a128f8ce6c..136c952f53 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.world.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -79,6 +80,30 @@ object IonChunkCommand : SLCommand() { } } + @Subcommand("dump") + @CommandCompletion("power") /* |item|gas") */ + fun dumpNetwork(sender: Player, network: String) { + val ionChunk = sender.chunk.ion() + + val grid = when (network) { + "power" -> ionChunk.transportNetwork.powerNetwork +// "item" -> ionChunk.transportNetwork.pipeGrid +// "gas" -> ionChunk.transportNetwork.gasGrid + else -> fail { "invalid network" } + } + + sender.information("${grid.nodes.size} covered position(s).") + sender.information("${grid.nodes.values.distinct().size} unique node(s).") + sender.information("${grid.extractors.size} extractor node(s).") + + when (grid) { + is ChunkPowerNetwork -> { + sender.information("${grid.solarPanels.size} solar panels") + sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") + } + } + } + @Subcommand("rebuild nodes") @CommandCompletion("power") /* |item|gas") */ fun rebuildNodes(sender: Player, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index ce6e78eaaf..a2ebf2da24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -36,7 +36,7 @@ class ChunkTransportManager( // gasGrid.setup() } - val tickExecutor = IntervalExecutor(5) { scope.launch { + val tickExecutor = IntervalExecutor(40) { scope.launch { powerNetwork.tick() }} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index ed70f783bc..7deaf71504 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -79,7 +79,6 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( override suspend fun tick() { tickSolars() tickExtractors() -// tickExecutor() } /** @@ -103,21 +102,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - /** - * Find a destination by stepping along transferable nodes and following their rules - **/ - fun findDestination(origin: TransportNode) { - var steps = 1 - var current: TransportNode = origin - - while (steps < MAX_DEPTH) { - - steps++ - } - } companion object { const val POWER_EXTRACTOR_STEP = 1000 - const val MAX_DEPTH = 200 } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 680347c83b..2068b15e8e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -20,29 +20,21 @@ data class NodeRelationship( * Break the relation between the two nodes **/ fun breakUp() { - println("Removing ${sideOne.node}'s relation to ${sideTwo.node}") sideOne.node.removeRelationship(sideTwo.node) - println("Removing ${sideTwo.node}'s relation to ${sideOne.node}") sideTwo.node.removeRelationship(sideOne.node) } companion object { fun create(nodeOne: TransportNode, nodeTwo: TransportNode) { - println("Attempting to create relationship between $nodeOne and $nodeTwo") Throwable().printStackTrace() val canTransferTo = nodeOne.isTransferableTo(nodeTwo) val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) - println("Node one can transfer to node two: $canTransferTo") - println("Node two can transfer to node one: $canTransferFrom") - // Do not add the relationship if neither side can transfer if (!canTransferFrom && !canTransferTo) return - println("Adding a relation between $nodeOne and $nodeTwo") nodeOne.relationships += NodeRelationship(RelationSide(nodeOne, canTransferTo), RelationSide(nodeTwo, canTransferFrom)) - println("Adding a relation between $nodeTwo and $nodeOne") nodeTwo.relationships += NodeRelationship(RelationSide(nodeTwo, canTransferFrom), RelationSide(nodeOne, canTransferTo)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 7d8c27597d..3915104d91 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -27,7 +27,6 @@ interface TransportNode : PDCSerializable = ObjectOpenHashSet() - val extractableNodes: MutableSet get() = getTransferableNodes().mapNotNullTo(mutableSetOf()) { it as? PowerInputNode } + val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } val useful get() = extractableNodes.size >= 1 @@ -74,7 +74,9 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, // Nothing can transfer to extractors step as PowerOriginStep - val next = relationships.randomOrNull()?.sideTwo?.node ?: return + val next = getTransferableNodes().randomOrNull() ?: return + + println("Next node is $next") // Simply move on to the next node TransportStep(step, step.steps, next, step).invoke() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 6697ff13cc..870fdad83d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -94,6 +94,8 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { } } + if (step.origin.currentNode is SolarPanelNode) return + // println(""" // // Reached multiblock input diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 6ee7694ce8..7fa3e1579d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -164,8 +164,9 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { - val previousNode = step.previous.currentNode - val next = getTransferableNodes().filterNot { it == previousNode }.randomOrNull() ?: return + val next = getTransferableNodes() + .filterNot { step.traversedNodes.contains(it) } + .randomOrNull() ?: return // Simply move on to the next node TransportStep( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index ce9dd12442..e0c32331e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -58,8 +58,11 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode suspend operator fun invoke() { if (steps.incrementAndGet() > MAX_DEPTH) return + traversedNodes.add(currentNode) currentNode.handleStep(this) + +// println(""" +// Step has been invoked +// $steps steps taken +// currently on $currentNode +// has $share share +// traversed through $traversedNodes +// """.trimIndent()) } companion object { @@ -24,7 +34,9 @@ data class PowerOriginStep( override val currentNode: TransportNode, var power: Int, override val share: Float = 1f -) : Step +) : Step { + override val traversedNodes: MutableList = mutableListOf() +} data class TransportStep( val origin: PowerOriginStep, @@ -32,4 +44,6 @@ data class TransportStep( override val currentNode: TransportNode, val previous: Step, override val share: Float = 1f -) : Step +) : Step { + override val traversedNodes: MutableList = mutableListOf() +} From dfb84c26bc3b62f578bf7add64272e2c4b3d7729 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 10 May 2024 14:42:17 -0500 Subject: [PATCH 055/500] fixes, add power flow meter basic implementation --- .../transport/network/ChunkPowerNetwork.kt | 4 +- .../features/transport/node/NodeType.kt | 2 + .../features/transport/node/TransportNode.kt | 6 ++ .../transport/node/power/EndRodNode.kt | 4 +- .../node/power/PowerExtractorNode.kt | 7 +- .../transport/node/power/PowerFlowMeter.kt | 80 +++++++++++++++++++ .../transport/node/power/PowerInputNode.kt | 7 ++ .../transport/node/power/PowerNodeFactory.kt | 7 ++ .../transport/node/power/SolarPanelNode.kt | 5 +- .../transport/node/power/SpongeNode.kt | 4 +- .../server/features/transport/step/Step.kt | 12 ++- 11 files changed, 120 insertions(+), 18 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index 7deaf71504..90ca2862de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -55,7 +55,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( if (power <= 0) continue - runCatching { solarPanel.handleStep(PowerOriginStep(AtomicInteger(), solarPanel, power)) }.onFailure { + runCatching { solarPanel.handleStep(PowerOriginStep(AtomicInteger(), solarPanel, power, mutableSetOf(solarPanel))) }.onFailure { IonServer.slF4JLogger.error("Exception ticking solar panel! $it") it.printStackTrace() } @@ -70,7 +70,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( val sum = extractablePowerPool.sumOf { it.getPower() } val extractablePower = min(sum, POWER_EXTRACTOR_STEP) - runCatching { extractor.handleStep(PowerOriginStep(AtomicInteger(), extractor, extractablePower)) }.onFailure { + runCatching { extractor.handleStep(PowerOriginStep(AtomicInteger(), extractor, extractablePower, mutableSetOf(extractor))) }.onFailure { it.printStackTrace() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index d67aa8839b..1b95fe1270 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -4,6 +4,7 @@ import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.power.SpongeNode @@ -15,6 +16,7 @@ enum class NodeType(val clazz: Class) { SOLAR_PANEL_NODE(SolarPanelNode::class.java), POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), + POWER_FLOW_METER(PowerFlowMeter::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 3915104d91..aaedc37506 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable @@ -101,6 +102,11 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 161b4bfd69..de00a7fb1b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -55,6 +55,7 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode() + + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + this.position = position + } + + override val relationships: MutableSet = ObjectOpenHashSet() + + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is SourceNode + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } + + override suspend fun handleStep(step: Step) { + // This is not an origin node, so we can assume that it is not an origin step + step as TransportStep + + val next = getTransferableNodes() + .filterNot { step.traversedNodes.contains(it) } + .filterNot { step.previous.currentNode == it } + .randomOrNull() ?: return + + println("Next node is $next") + + // Simply move on to the next node + TransportStep( + step.origin, + step.steps, + next, + step, + step.traversedNodes + ).invoke() + } + + private var lastStepped: Long = System.currentTimeMillis() + private var steps: Int = 1 + private val averages = EvictingQueue.create(10) + + override suspend fun onCompleteChain(final: Step, destination: PowerInputNode, transferred: Int) { + final as TransportStep + + val time = System.currentTimeMillis() + val diff = time - lastStepped + lastStepped = time + + steps++ + + val seconds = diff / 1000.0 + averages.add(transferred / seconds) + + network.world.sendMessage(Component.text("Running average transferred is ${averages.average()}")) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 870fdad83d..cdc0634700 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -69,6 +69,8 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { } override suspend fun handleStep(step: Step) { + step.traversedNodes.add(this) + // This is not an origin node, so we can assume that it is not an origin step step as TransportStep @@ -94,6 +96,11 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { } } + println("Traversed nodes: ${step.traversedNodes}") + step.traversedNodes.forEach { + it.onCompleteChain(step, this, share) + } + if (step.origin.currentNode is SolarPanelNode) return // println(""" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 6b8f5e5702..0e698baf3c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -54,6 +54,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory addInput(key) + snapshot.type == Material.OBSERVER -> addFlowMeter(key) // Merge node behavior // block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) @@ -127,6 +128,12 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory throw NotImplementedError("Unrecognized step type $step") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index e0c32331e6..0c0663a5ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -60,6 +60,7 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode + val traversedNodes: MutableSet suspend operator fun invoke() { if (steps.incrementAndGet() > MAX_DEPTH) return @@ -33,17 +33,15 @@ data class PowerOriginStep( override val steps: AtomicInteger, override val currentNode: TransportNode, var power: Int, + override val traversedNodes: MutableSet, override val share: Float = 1f -) : Step { - override val traversedNodes: MutableList = mutableListOf() -} +) : Step data class TransportStep( val origin: PowerOriginStep, override val steps: AtomicInteger, override val currentNode: TransportNode, val previous: Step, + override val traversedNodes: MutableSet, override val share: Float = 1f -) : Step { - override val traversedNodes: MutableList = mutableListOf() -} +) : Step From 882616f22d7e3af399134a4f077f637aa99e1608 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 10 May 2024 17:44:29 -0500 Subject: [PATCH 056/500] reliability improvements, network version migration --- .../server/command/admin/IonChunkCommand.kt | 55 ++++---------- .../multiblock/ChunkMultiblockManager.kt | 2 +- .../entity/MultiblockEntityFixer.kt | 2 +- .../transport/ChunkTransportManager.kt | 4 +- .../transport/network/ChunkPowerNetwork.kt | 8 ++ .../network/ChunkTransportNetwork.kt | 76 ++++++++++++------- .../transport/node/NodeRelationship.kt | 2 - .../features/transport/node/NodeUtils.kt | 27 ++++++- .../transport/node/power/EndRodNode.kt | 1 - .../ion/server/features/world/IonWorld.kt | 1 + .../features/world/chunk/ChunkRelation.kt | 9 +++ .../features/world/{ => chunk}/IonChunk.kt | 3 +- .../features/world/data/ChunkDataFixer.kt | 2 +- .../miscellaneous/registrations/Listeners.kt | 2 +- 14 files changed, 111 insertions(+), 83 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRelation.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/world/{ => chunk}/IonChunk.kt (98%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 136c952f53..9f1487841d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -14,7 +14,8 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork -import net.horizonsend.ion.server.features.world.IonChunk.Companion.ion +import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text @@ -61,15 +62,9 @@ object IonChunkCommand : SLCommand() { @Subcommand("dump nodes") @CommandCompletion("power") /* |item|gas") */ - fun dumpNodes(sender: Player, network: String) { + fun dumpNodes(sender: Player, network: NetworkType) { val ionChunk = sender.chunk.ion() - - val grid = when (network) { - "power" -> ionChunk.transportNetwork.powerNetwork -// "item" -> ionChunk.transportNetwork.pipeGrid -// "gas" -> ionChunk.transportNetwork.gasGrid - else -> fail { "invalid network" } - } + val grid = network.get(ionChunk) sender.information("${grid.nodes.size} covered position(s).") sender.information("${grid.nodes.values.distinct().size} unique node(s).") @@ -81,16 +76,10 @@ object IonChunkCommand : SLCommand() { } @Subcommand("dump") - @CommandCompletion("power") /* |item|gas") */ - fun dumpNetwork(sender: Player, network: String) { + @CommandCompletion("power") + fun dumpNetwork(sender: Player, network: NetworkType) { val ionChunk = sender.chunk.ion() - - val grid = when (network) { - "power" -> ionChunk.transportNetwork.powerNetwork -// "item" -> ionChunk.transportNetwork.pipeGrid -// "gas" -> ionChunk.transportNetwork.gasGrid - else -> fail { "invalid network" } - } + val grid = network.get(ionChunk) sender.information("${grid.nodes.size} covered position(s).") sender.information("${grid.nodes.values.distinct().size} unique node(s).") @@ -106,15 +95,9 @@ object IonChunkCommand : SLCommand() { @Subcommand("rebuild nodes") @CommandCompletion("power") /* |item|gas") */ - fun rebuildNodes(sender: Player, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { + fun rebuildNodes(sender: Player, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { val ionChunk = sender.chunk.ion() - - val grid = when (network) { - "power" -> ionChunk.transportNetwork.powerNetwork -// "item" -> ionChunk.transportNetwork.pipeGrid -// "gas" -> ionChunk.transportNetwork.gasGrid - else -> return@launch fail { "invalid network" } - } + val grid = network.get(ionChunk) grid.nodes.clear() grid.extractors.clear() @@ -129,32 +112,20 @@ object IonChunkCommand : SLCommand() { } @Subcommand("get node key") - fun getNode(sender: Player, key: Long, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { + fun getNode(sender: Player, key: Long, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { val ionChunk = sender.chunk.ion() - - val grid = when (network) { - "power" -> ionChunk.transportNetwork.powerNetwork -// "item" -> ionChunk.transportNetwork.pipeGrid -// "gas" -> ionChunk.transportNetwork.gasGrid - else -> return@launch fail { "invalid network" } - } + val grid = network.get(ionChunk) sender.information("Targeted node: ${grid.nodes[key]}") } @Subcommand("get node look") - fun getNode(sender: Player, network: String) = CoroutineScope(Dispatchers.Default + Job()).launch { + fun getNode(sender: Player, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { val ionChunk = sender.chunk.ion() + val grid = network.get(ionChunk) val targeted = sender.getTargetBlock(null, 10) val key = toBlockKey(targeted.x, targeted.y, targeted.z) - val grid = when (network) { - "power" -> ionChunk.transportNetwork.powerNetwork -// "item" -> ionChunk.transportNetwork.pipeGrid -// "gas" -> ionChunk.transportNetwork.gasGrid - else -> return@launch fail { "invalid network" } - } - sender.information("Targeted node: ${grid.nodes[key]}") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 69b199b3ca..301870236a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock -import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt index e3201aeaf8..0460608078 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity -import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.data.DataFixer object MultiblockEntityFixer : DataFixer { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index a2ebf2da24..96fb2508b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork -import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -24,7 +24,7 @@ class ChunkTransportManager( val extractorData = getExtractorData(chunk.inner) - val powerNetwork = ChunkPowerNetwork(this).apply { loadData(); build() } + val powerNetwork = ChunkPowerNetwork(this).apply { build() } // val pipeGrid = ChunkPowerNetwork(this) // TODO // val gasGrid = ChunkPowerNetwork(this) // TODO diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index 90ca2862de..d391b71912 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -33,6 +33,8 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() + override val dataVersion: Int = 0 //TODO 1 + override fun setup() { collectPowerMultiblockEntities() } @@ -81,6 +83,12 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( tickExtractors() } + override suspend fun clearData() { + nodes.clear() + solarPanels.clear() + extractors.clear() + } + /** * Handle the addition of a new powered multiblock entity **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index a8e6c1a137..79ba849ff8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.seconds import org.bukkit.NamespacedKey @@ -30,6 +30,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { protected abstract val namespacedKey: NamespacedKey abstract val nodeFactory: NodeFactory<*> + abstract val dataVersion: Int // val grids: Nothing = TODO("ChunkTransportNetwork system") @@ -49,22 +50,32 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { /** * Load stored node data from the chunk + * + * @return Whether the data was intact, or up to date **/ - fun loadData() { - val existing = pdc.get(POWER_TRANSPORT, PersistentDataType.TAG_CONTAINER) ?: return + fun loadData(): Boolean { + val existing = pdc.get(namespacedKey, PersistentDataType.TAG_CONTAINER) ?: return false + val version = pdc.getOrDefault(DATA_VERSION, PersistentDataType.INTEGER, 0) + + if (version < dataVersion) { + IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained outdated data! It will be rebuilt") + return false + } // Deserialize once val nodeData = existing.getOrDefault(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).mapNotNull { runCatching { TransportNode.load(it, this) }.onFailure { - IonServer.slF4JLogger.error("Error deserializing multiblock data! $it") + IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained corrupted data! It will be rebuilt") it.printStackTrace() - }.getOrNull() + }.getOrElse { return false } } nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { - IonServer.slF4JLogger.error("Error loading node into network!") + IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} loading node into network!") it.printStackTrace() - } } + }.onFailure { return false } } + + return true } fun save(adapterContext: PersistentDataAdapterContext) { @@ -80,24 +91,44 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { pdc.set(namespacedKey, PersistentDataType.TAG_CONTAINER, container) - saveAdditional() + saveAdditional(pdc) } - open fun saveAdditional() {} + open fun saveAdditional(pdc: PersistentDataContainer) {} /** * **/ abstract suspend fun tick() + abstract suspend fun clearData() + + /** + * Logic for when the holding chunk is unloaded + **/ + open fun onUnload() { + // Break cross chunk relations + breakAllRelations() + + save(manager.chunk.inner.persistentDataContainer.adapterContext) + } + /** - * Builds the transportNetwork TODO better documentation + * Builds the transportNetwork + * + * Existing data will be loaded from the chunk's persistent data container, relations between nodes will be built, and any finalization will be performed **/ fun build() = manager.scope.launch { -// collectAllNodes().join() + if (!loadData()) { + clearData() + collectAllNodes().join() + } + + // Save rebuilt data + save(manager.chunk.inner.persistentDataContainer.adapterContext) + buildRelations() finalizeNodes() - buildGraph() } /** @@ -147,25 +178,16 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { } /** - * Consolidates network nodes where possible - * - * e.g. a straight section may be represented as a single node + * Handles any cleanup tasks at the end of loading **/ - private fun finalizeNodes() { -// nodes.forEach { (_, node) -> -// -// } - } - - /** - * - **/ - private fun buildGraph() { - //TODO - } + open fun finalizeNodes() {} fun getNode(x: Int, y: Int, z: Int): TransportNode? { val key = toBlockKey(x, y, z) return nodes[key] } + + fun breakAllRelations() { + nodes.values.forEach { it.clearRelations() } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 2068b15e8e..fc5828625a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -26,8 +26,6 @@ data class NodeRelationship( companion object { fun create(nodeOne: TransportNode, nodeTwo: TransportNode) { - Throwable().printStackTrace() - val canTransferTo = nodeOne.isTransferableTo(nodeTwo) val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index de04243a0b..da7340f253 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.transport.node +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -9,6 +11,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull +import org.bukkit.World import org.bukkit.block.BlockFace fun getNeighborNodes(position: BlockKey, nodes: Map, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { @@ -27,9 +30,6 @@ fun getNeighborNodes(position: BlockKey, nodes: Collection, checkFaces toBlockKey(x + it.modX, y + it.modY, z + it.modZ).takeIf { key -> nodes.contains(key) } } -inline fun getMatchingNeighborNodes(position: BlockKey, nodes: Map): MutableList = - getNeighborNodes(position, nodes).values.filterIsInstanceTo>(mutableListOf()) - /** * Merge the provided nodes into the largest node [by position] in the collection * @@ -48,3 +48,24 @@ suspend fun > handleMerges(neighbors: MutableCollect return largestNeighbor } + +fun getNode(world: World, key: BlockKey, networkType: NetworkType): TransportNode? { + val x = getX(key).shr(4) + val z = getZ(key).shr(4) + + val chunk = IonChunk[world, x, z] ?: return null + return networkType.get(chunk).nodes[key] +} + +enum class NetworkType { + POWER { + override fun get(chunk: IonChunk): ChunkTransportNetwork { + return chunk.transportNetwork.powerNetwork + } + } + + + ; + + abstract fun get(chunk: IonChunk): ChunkTransportNetwork +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index de00a7fb1b..7d7f15771e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -60,7 +60,6 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode> get() = inner.minecraft.sections.withIndex() // TODO - // - Wires // - Ore upgrader // - Explosion Reversal diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt index b882e55fe7..e89ba8f52d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.world.data import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntityFixer -import net.horizonsend.ion.server.features.world.IonChunk +import net.horizonsend.ion.server.features.world.chunk.IonChunk object ChunkDataFixer { const val DATA_VERSION = 1 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 4b1a64be67..60cdc2a694 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -14,8 +14,8 @@ import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager import net.horizonsend.ion.server.features.waypoint.WaypointListeners -import net.horizonsend.ion.server.features.world.IonChunk import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager import net.horizonsend.ion.server.listener.fixers.BiomeFixer9001 import net.horizonsend.ion.server.listener.fixers.CancelListeners From c1c96b1b80acf361c6558abb5a4ba3fd91344c84 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 12 May 2024 16:52:33 -0500 Subject: [PATCH 057/500] chunk regions, coroutine work --- .../server/command/admin/IonChunkCommand.kt | 10 ++ .../multiblock/util/AsyncBlockUtils.kt | 25 +++- .../transport/ChunkTransportManager.kt | 17 +-- .../transport/node/power/EndRodNode.kt | 2 - .../node/power/PowerExtractorNode.kt | 2 - .../transport/node/power/PowerFlowMeter.kt | 2 - .../transport/node/power/PowerInputNode.kt | 2 +- .../transport/node/power/SpongeNode.kt | 2 - .../ion/server/features/world/IonWorld.kt | 9 +- .../features/world/chunk/ChunkRegion.kt | 124 ++++++++++++++++++ .../server/features/world/chunk/IonChunk.kt | 21 +-- 11 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 9f1487841d..ca6c102a17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -93,6 +94,15 @@ object IonChunkCommand : SLCommand() { } } + @Subcommand("dumpchunk") + fun dumpChunk(sender: Player) { + val ionChunk = sender.chunk.ion() + + sender.information("Chunk: $ionChunk") + sender.information("Region: ${ionChunk.region}") + sender.information("World has: ${ionChunk.world.ion.regionPositions.values.distinct().size} unique regions") + } + @Subcommand("rebuild nodes") @CommandCompletion("power") /* |item|gas") */ fun rebuildNodes(sender: Player, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index 79d796aa9d..abccbd85ef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -10,12 +10,15 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.loadChunkAsync +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.core.BlockPos import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.chunk.LevelChunk +import org.bukkit.Bukkit import org.bukkit.ChunkSnapshot import org.bukkit.Material import org.bukkit.World @@ -43,7 +46,22 @@ suspend fun getChunkSnapshotAsync(world: World, x: Int, z: Int, loadChunks: Bool /** Retrieves a snapshot of an async block */ suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): BlockSnapshot? { - return getChunkSnapshotAsync(world, x, z, loadChunks)?.getBlockSnapshot(x, y, z) + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + if (world.isChunkLoaded(chunkX, chunkZ)) { + val type = getBlockTypeSafe(world, x, y, z) ?: return null + val data = getBlockDataSafe(world, x, y, z) ?: return null + + return BlockSnapshot(world, x, y, z, type, data) + } + + if (!loadChunks) return null + + val chunk = world.getChunkAtAsync(x, z).asDeferred().await() + val state = chunk.minecraft.getBlockState(x, y, z) + + return BlockSnapshot(world, x, y, z, state.bukkitMaterial, CraftBlockData.fromData(state)) } /** Retrieves a snapshot of an async block */ @@ -88,6 +106,11 @@ suspend fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { suspend fun getAndCastNMSTileEntity(block: Block, loadChunks: Boolean): T? = getNMSTileEntity(block, loadChunks) as? T suspend fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlockState? { + // If this is the main thread, we don't need to do laggy reflection + if (Bukkit.isPrimaryThread()) { + return block.state + } + val world = block.world val blockPos = (block as CraftBlock).position val data = getBlockSnapshotAsync(world, blockPos.x, blockPos.y, blockPos.z, loadChunks)?.data ?: return null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 96fb2508b7..636e93156a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -1,15 +1,11 @@ package net.horizonsend.ion.server.features.transport -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Chunk import org.bukkit.event.block.BlockBreakEvent @@ -20,28 +16,21 @@ class ChunkTransportManager( val chunk: IonChunk, ) { // Each chunk gets a scope for parallelism - val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) - val extractorData = getExtractorData(chunk.inner) + val scope = ChunkRegion.scope val powerNetwork = ChunkPowerNetwork(this).apply { build() } // val pipeGrid = ChunkPowerNetwork(this) // TODO // val gasGrid = ChunkPowerNetwork(this) // TODO - - fun setup() { powerNetwork.setup() // pipeGrid.setup() // gasGrid.setup() } - val tickExecutor = IntervalExecutor(40) { scope.launch { + suspend fun tick() { powerNetwork.tick() - }} - - fun tick() { - tickExecutor() } fun save() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 7d7f15771e..7b72d11898 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -58,8 +58,6 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode = ConcurrentHashMap() + val regionPositions: ConcurrentHashMap = ConcurrentHashMap() + val chunkRegions: MutableSet = ObjectOpenHashSet() /** * Gets the IonChunk at the specified coordinates if it is loaded @@ -170,8 +174,9 @@ class IonWorld private constructor( log.warn("Exception while ticking starship!", result) } - for ((_, chunk) in ionWorld.chunks) { - chunk.tick() + for (region in ionWorld.chunkRegions) { + val result = runCatching { region.tick() }.exceptionOrNull() ?: continue + log.warn("Exception while ticking chunk region!", result) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt new file mode 100644 index 0000000000..17476df2ae --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -0,0 +1,124 @@ +package net.horizonsend.ion.server.features.world.chunk + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor +import org.bukkit.Chunk +import java.util.concurrent.ForkJoinPool + +class ChunkRegion(val world: IonWorld) { + val chunks = Long2ObjectOpenHashMap() + + val size get() = chunks.long2ObjectEntrySet().size + + val tickChunkTransport = IntervalExecutor(40) { + + scope.launch { + for ((_, chunk) in chunks) { + chunk.transportNetwork.tick() + chunk.multiblockManager.tick() + } + } + } + + fun tick() { + tickChunkTransport.invoke() + + for ((key, chunk) in chunks) chunk.tick() + } + + fun removeChunk(chunk: IonChunk) { + chunks.remove(chunk.locationKey) + } + + fun delete() { + chunks.forEach { + world.regionPositions.remove(it.value.locationKey) + } + world.chunkRegions.remove(this) + } + + companion object { + val scope = CoroutineScope(ForkJoinPool(64).asCoroutineDispatcher() + SupervisorJob()) + const val MAX_SIZE: Int = 50 + + fun loadChunk(chunk: Chunk) { + val region: ChunkRegion = findRegion(chunk) + val ionChunk = IonChunk.registerChunk(chunk, region) + + val key = chunk.chunkKey + + region.chunks[key] = ionChunk + chunk.world.ion.regionPositions[key] = region + } + + fun unloadChunk(chunk: IonChunk) { + val region = chunk.region + + region.removeChunk(chunk) + + if (region.chunks.isEmpty()) region.delete() + } + + /** + * Will find a region for this chunk to join. + * + * If this chunk borders a region, and it can add another safely, join it. + * + * If there are two disconnected regions joined by this chunk, and they total less than the limit, combine them. + * + * If there is no region available, start a new one. + * + * Returns the region + **/ + fun findRegion(chunk: Chunk): ChunkRegion { + val neighbors = getNeighborRegions(chunk) + + val region: ChunkRegion = when (neighbors.size) { + 0 -> startNewRegion(chunk) + 1 -> { + val region = neighbors.first() + if (region.size > MAX_SIZE) startNewRegion(chunk) else region + } + in 2..4 -> { + neighbors.firstOrNull { it.size < MAX_SIZE } ?: startNewRegion(chunk) + } + else -> throw IllegalArgumentException() + } + + return region + } + + private fun getNeighborRegions(chunk: Chunk): Collection { + val chunkX = chunk.x + val chunkZ = chunk.z + + return CARDINAL_BLOCK_FACES.mapNotNull { direction -> + val newX = direction.modX + chunkX + val newZ = direction.modZ + chunkZ + + val key = Chunk.getChunkKey(newX, newZ) + chunk.world.ion.regionPositions[key] + } + } + + fun startNewRegion(chunk: Chunk): ChunkRegion { + val world = chunk.world.ion + val region = ChunkRegion(world) + world.chunkRegions.add(region) + + return region + } + } + + override fun toString(): String { + return "IonChunkRegion[${size} positions]" + } +} + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 5bd4508c03..e191fd13f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -19,7 +19,10 @@ import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.INTEGER -class IonChunk(val inner: Chunk) { +class IonChunk( + val inner: Chunk, + val region: ChunkRegion, +) { val dataVersion = inner.persistentDataContainer.getOrDefault(NamespacedKeys.DATA_VERSION, INTEGER, 0) val locationKey = inner.chunkKey @@ -69,10 +72,7 @@ class IonChunk(val inner: Chunk) { /** * Logic upon world tick **/ - fun tick() { - transportNetwork.tick() - multiblockManager.tick() - } + fun tick() {} /** * Gets the neighboring chunk in this direction @@ -89,7 +89,7 @@ class IonChunk(val inner: Chunk) { companion object : SLEventListener() { @EventHandler fun onChunkLoad(event: ChunkLoadEvent) { - registerChunk(event.chunk) + ChunkRegion.loadChunk(event.chunk) } @EventHandler @@ -114,10 +114,11 @@ class IonChunk(val inner: Chunk) { * * It is imperative that every exception generated be handled **/ - private fun registerChunk(chunk: Chunk): IonChunk { + fun registerChunk(chunk: Chunk, region: ChunkRegion): IonChunk { val ionWorld = chunk.world.ion - val ionChunk = IonChunk(chunk) + val ionChunk = IonChunk(chunk, region) + region.chunks[chunk.chunkKey] = ionChunk ionWorld.addChunk(ionChunk) @@ -138,6 +139,7 @@ class IonChunk(val inner: Chunk) { val removed = ionWorld.removeChunk(chunk) ?: return removed.onUnload() + ChunkRegion.unloadChunk(removed) } /** @@ -148,6 +150,9 @@ class IonChunk(val inner: Chunk) { } fun Chunk.ion(): IonChunk = this.world.ion.getChunk(chunkKey)!! + + fun getXFromKey(key: Long): Int = key.toInt() + fun getZFromKey(key: Long): Int = (key shr 32).toInt() } override fun toString(): String { From 55a58f7be96bec23d7e0e5c94efe2e5fc42472f7 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 12 May 2024 22:53:48 -0500 Subject: [PATCH 058/500] cross chunk power transfer --- .../transport/ChunkTransportManager.kt | 30 ++++++------ .../transport/network/ChunkPowerNetwork.kt | 9 +++- .../network/ChunkTransportNetwork.kt | 41 +++++++++++++--- .../node/power/PowerExtractorNode.kt | 2 +- .../transport/node/power/PowerFlowMeter.kt | 49 +++++++++++++++---- .../features/transport/node/type/MultiNode.kt | 2 +- .../transport/node/type/SingleNode.kt | 2 +- .../server/features/world/chunk/IonChunk.kt | 1 + .../server/miscellaneous/utils/Collections.kt | 10 ++++ 9 files changed, 111 insertions(+), 35 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 636e93156a..46e9919f15 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -5,19 +5,13 @@ import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Compani import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.Chunk import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent -import java.util.concurrent.ConcurrentLinkedQueue class ChunkTransportManager( val chunk: IonChunk, ) { - // Each chunk gets a scope for parallelism - val extractorData = getExtractorData(chunk.inner) - val scope = ChunkRegion.scope val powerNetwork = ChunkPowerNetwork(this).apply { build() } // val pipeGrid = ChunkPowerNetwork(this) // TODO @@ -25,16 +19,26 @@ class ChunkTransportManager( fun setup() { powerNetwork.setup() -// pipeGrid.setup() -// gasGrid.setup() + // TODO + // TODO } suspend fun tick() { powerNetwork.tick() + // TODO + // TODO + } + + fun onUnload() { + powerNetwork.onUnload() + // TODO + // TODO } fun save() { powerNetwork.save(chunk.inner.persistentDataContainer.adapterContext) + // TODO + // TODO } fun processBlockRemoval(event: BlockBreakEvent) { @@ -55,19 +59,17 @@ class ChunkTransportManager( fun processBlockRemoval(key: Long) { powerNetwork.processBlockRemoval(key) + // TODO + // TODO // pipeGrid.processBlockRemoval(key) // gasGrid.processBlockRemoval(key) } fun processBlockAddition(key: Long, new: BlockSnapshot) { powerNetwork.processBlockAddition(key, new) + // TODO + // TODO // pipeGrid.processBlockAddition(key, new) // gasGrid.processBlockAddition(key, new) } - - private fun getExtractorData(chunk: Chunk): ExtractorData { - val extractors = chunk.persistentDataContainer.get(NamespacedKeys.EXTRACTOR_DATA, ExtractorData) - - return extractors ?: ExtractorData(ConcurrentLinkedQueue()) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index d391b71912..a7f8b804a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode @@ -25,11 +26,15 @@ import java.util.concurrent.atomic.AtomicInteger import kotlin.math.min class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { - val poweredMultiblockEntities = ConcurrentHashMap() - + override val type: NetworkType = NetworkType.POWER override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) + /** + * A list of all the powered multiblock entities within the chunk + **/ + val poweredMultiblockEntities = ConcurrentHashMap() + /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index 79ba849ff8..e2b6552f3d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -7,11 +7,16 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.seconds import org.bukkit.NamespacedKey @@ -29,11 +34,10 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val pdc get() = manager.chunk.inner.persistentDataContainer protected abstract val namespacedKey: NamespacedKey + protected abstract val type: NetworkType abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int -// val grids: Nothing = TODO("ChunkTransportNetwork system") - open fun setup() {} /** @@ -106,7 +110,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { /** * Logic for when the holding chunk is unloaded **/ - open fun onUnload() { + fun onUnload() { // Break cross chunk relations breakAllRelations() @@ -132,7 +136,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { } /** - * + * Build node data from an unregistered state **/ private fun collectAllNodes(): Job = manager.scope.launch { // Parallel collect the nodes of each section @@ -182,12 +186,37 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { **/ open fun finalizeNodes() {} + fun breakAllRelations() { + nodes.values.forEach { it.clearRelations() } + } + fun getNode(x: Int, y: Int, z: Int): TransportNode? { val key = toBlockKey(x, y, z) return nodes[key] } - fun breakAllRelations() { - nodes.values.forEach { it.clearRelations() } + /** + * Gets a node from this chunk, or a direct neighbor, if loaded + **/ + fun getNode(key: BlockKey, allowNeighborChunks: Boolean = true): TransportNode? { + val chunkX = getX(key).shr(4) + val chunkZ = getZ(key).shr(4) + + val isThisChunk = chunkX == manager.chunk.x && chunkZ == manager.chunk.z + + if (!allowNeighborChunks && isThisChunk) return null + + if (isThisChunk) { + return nodes[key] + } + + val xDiff = manager.chunk.x - chunkX + val zDiff = manager.chunk.z - chunkZ + + if (xDiff > 1 || xDiff < -1) return null + if (zDiff > 1 || zDiff < -1) return null + + val chunk = IonChunk[world, chunkX, chunkZ] ?: return null + return type.get(chunk).nodes[key] } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 543b517300..e43d94502b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -57,7 +57,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.nodes[offsetKey] ?: continue + val neighborNode = network.getNode(offsetKey) ?: continue if (this == neighborNode) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index d44c215fc1..c627cdc29a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.power -import com.google.common.collect.EvictingQueue import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship @@ -58,21 +57,51 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { } private var lastStepped: Long = System.currentTimeMillis() - private var steps: Int = 1 - private val averages = EvictingQueue.create(10) + + private val STORED_AVERAGES = 20 + private val averages = mutableListOf() override suspend fun onCompleteChain(final: Step, destination: PowerInputNode, transferred: Int) { final as TransportStep - val time = System.currentTimeMillis() - val diff = time - lastStepped - lastStepped = time + addAverage(TransferredPower(transferred, System.currentTimeMillis())) + + network.world.sendMessage(Component.text("Running average transferred is ${calculateAverage()}")) + } + + private fun addAverage(average: TransferredPower) { + val currentSize = averages.size + + if (currentSize < STORED_AVERAGES) { + averages.add(average) + return + } + + // If it is full, shift all averages to the right + for (index in 18 downTo 0) { + averages[index + 1] = averages[index] + } + + averages[0] = average + } + + fun calculateAverage(): Double { + println("Averages: $averages") + + val last = averages.first() + + println("Last: $last") - steps++ + val sum = averages.sumOf { it.transferred } - val seconds = diff / 1000.0 - averages.add(transferred / seconds) + println("Transferred sum: $sum") - network.world.sendMessage(Component.text("Running average transferred is ${averages.average()}")) + val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 + + println("Seconds diff $timeDiff") + + return sum / timeDiff } + + private data class TransferredPower(val transferred: Int, val time: Long) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 29f5a51ee0..61293fe258 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -59,7 +59,7 @@ interface MultiNode, Z: MultiNode> : Transport override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.nodes[offsetKey] ?: continue + val neighborNode = network.getNode(offsetKey) ?: continue if (this == neighborNode) continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 8119ab95ce..2ce254e18e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -18,7 +18,7 @@ interface SingleNode : TransportNode { override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.nodes[offsetKey] ?: continue + val neighborNode = network.getNode(offsetKey) ?: continue if (this == neighborNode) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index e191fd13f5..b534623fad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -59,6 +59,7 @@ class IonChunk( **/ fun onUnload() { save() + transportNetwork.onUnload() } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index 4190fef8cb..b596ad2022 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -128,3 +128,13 @@ inline fun Map.filterKeysIsInstance(): Map { @Suppress("UNCHECKED_CAST") return filterKeys { it is T } as Map } + +inline fun Collection.averageBy(transform: (T) -> Double): Double { + var total = 0.0 + + for (entry in this) { + total += transform(entry) + } + + return total / size +} From 9e4d72a922d25f3bfc25cb0f087b6893762307af Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 13 May 2024 00:46:33 -0500 Subject: [PATCH 059/500] temporarily make redstone / iron act like sponges, slightly smarter solar panel pathfinding --- .../transport/node/power/MergeNode.kt | 55 +++++++++++++++++++ .../transport/node/power/PowerFlowMeter.kt | 8 +-- .../transport/node/power/PowerNodeFactory.kt | 10 +++- .../transport/node/power/SolarPanelNode.kt | 8 +-- .../features/world/chunk/ChunkRegion.kt | 2 +- 5 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt new file mode 100644 index 0000000000..76a432a2cb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -0,0 +1,55 @@ +package net.horizonsend.ion.server.features.transport.node.power + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.TransportStep +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +class MergeNode(override val network: ChunkTransportNetwork) : SingleNode { + override val relationships: MutableSet = ObjectOpenHashSet() + override var position: BlockKey by Delegates.notNull() + + constructor(network: ChunkTransportNetwork, position: BlockKey) : this(network) { + this.position = position + } + + override suspend fun handleStep(step: Step) { + // This is not an origin node, so we can assume that it is not an origin step + step as TransportStep + + val next = getTransferableNodes() + .filterNot { step.traversedNodes.contains(it) } + .filterNot { step.previous.currentNode == it } + .randomOrNull() ?: return + + // Simply move on to the next node + TransportStep( + step.origin, + step.steps, + next, + step, + step.traversedNodes + ).invoke() + } + + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is SourceNode + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index c627cdc29a..5d864e84b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -86,19 +86,19 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { } fun calculateAverage(): Double { - println("Averages: $averages") +// println("Averages: $averages") val last = averages.first() - println("Last: $last") +// println("Last: $last") val sum = averages.sumOf { it.transferred } - println("Transferred sum: $sum") +// println("Transferred sum: $sum") val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 - println("Seconds diff $timeDiff") +// println("Seconds diff $timeDiff") return sum / timeDiff } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 0e698baf3c..1b9d515485 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -57,8 +57,8 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory addFlowMeter(key) // Merge node behavior -// block.type == Material.IRON_BLOCK -> MergeNode(this, x, y, z) -// block.type == Material.REDSTONE_BLOCK -> MergeNode(this, x, y, z) + snapshot.type == Material.IRON_BLOCK -> addSourceNode(key) + snapshot.type == Material.REDSTONE_BLOCK -> addSourceNode(key) // Split power evenly // block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) @@ -178,4 +178,10 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory { - val next = getTransferableNodes() - .filterNot { step.traversedNodes.contains(it) } - .randomOrNull() ?: return + val neighbors = getTransferableNodes() + val next = neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: neighbors.randomOrNull() ?: return // Simply move on to the next node TransportStep( @@ -179,7 +178,8 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode { - val next = getTransferableNodes().randomOrNull() ?: return + val neighbors = getTransferableNodes() + val next = neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: neighbors.randomOrNull() ?: return // Simply move on to the next node TransportStep(step, step.steps, next, step, step.traversedNodes).invoke() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index 17476df2ae..46ea1bfc9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -17,7 +17,7 @@ class ChunkRegion(val world: IonWorld) { val size get() = chunks.long2ObjectEntrySet().size - val tickChunkTransport = IntervalExecutor(40) { + val tickChunkTransport = IntervalExecutor(4) { scope.launch { for ((_, chunk) in chunks) { From 33adef8c1eaa0bb40aeb8671f6166eed430b620c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 15 May 2024 13:21:10 -0500 Subject: [PATCH 060/500] improved solar pathfinding, cleanup --- .../transport/node/power/SolarPanelNode.kt | 170 +++++++++++------- 1 file changed, 107 insertions(+), 63 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 4b9c54b67a..29e5b0c075 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -21,6 +21,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LONG_ARRAY +import java.util.function.Consumer import kotlin.math.PI import kotlin.math.max import kotlin.math.sin @@ -30,13 +31,98 @@ import kotlin.math.sin **/ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, SourceNode { override val positions: MutableSet = LongOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() + /** The positions of extractors in this solar panel */ - val extractorPositions = LongOpenHashSet() + private val extractorPositions = LongOpenHashSet() /** The number of solar cells contained in this node */ - val cellNumber: Int get() = extractorPositions.size + private val cellNumber: Int get() = extractorPositions.size - override val relationships: MutableSet = ObjectOpenHashSet() + /** + * The distance this solar node is from the nearest exit of the solar field + * This value will be -1 if there are no exits present + **/ + private var exitDistance: Int = 0 + + private var lastTicked: Long = System.currentTimeMillis() + + /** + * Returns the amount of power between ticks + **/ + fun getPower(): Int { + val daylightMultiplier: Double = if ( + network.world.environment == World.Environment.NORMAL && + network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true + ) { + val daylight = sin((network.world.time / (12000.0 / PI)) - (PI / 2)) + max(0.0, daylight) * 1.5 // 1.5 to bring area under curve to around equal with night + } else 0.5 + + val time = System.currentTimeMillis() + val diff = time - this.lastTicked + + return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() + } + + /** + * Get the power and reset the last ticked time + **/ + fun tickAndGetPower(): Int { + val power = getPower() + lastTicked = System.currentTimeMillis() + + return power + } + + /** + * Calculate the distance to an exit of a solar field + * This method is run upon neighbor unloads + **/ + private fun calculateExitDistance() { + val neighbors = getTransferableNodes() + + // Borders an exit + if (neighbors.any { it !is SolarPanelNode }) { + exitDistance = 0 + return + } + + val solars = neighbors.filterIsInstance() + if (solars.isEmpty()) { + exitDistance = -1 + return + } + + exitDistance = solars.minOf { it.exitDistance } + 1 + } + + /** + * Execute the provided consumer across every interconnected solar node + * + * WARNING: use this carefully + **/ + private fun traverseField(visited: MutableList = mutableListOf(), consumer: Consumer) { + if (visited.contains(this)) return + + consumer.accept(this) + + getTransferableNodes().filterIsInstance().filterNot { visited.contains(it) }.forEach(consumer) + } + + /** + * Returns whether the individual solar panel from the extractor location is intact + **/ + suspend fun isIntact(world: World, extractorKey: BlockKey): Boolean { + return matchesSolarPanelStructure(world, extractorKey) + } + + // If relations have changed, update the exit distances of the whole field + override suspend fun buildRelations(position: BlockKey) { + traverseField { it.calculateExitDistance() } + + super.buildRelations(position) + } override fun isTransferableTo(node: TransportNode): Boolean { // Solar panels should be able to transfer through extractors and other solar panels @@ -96,13 +182,13 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode) { + private fun removePosition(extractorKey: BlockKey, others: Iterable) { extractorPositions -= extractorKey - network.nodes.remove(extractorKey) positions.remove(extractorKey) + network.nodes.remove(extractorKey) + positions.removeAll(others.toSet()) - positions += others - for (position: BlockKey in positions) { + for (position: BlockKey in others) { network.nodes.remove(position) } } @@ -127,66 +213,25 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode() + .shuffled() // Make sure the lowest priority, if multiple is random every time + .minByOrNull { it.exitDistance } } + // Solar panel pathfinding logic: + // Find the closest exit from the solar fiend and transfer to it override suspend fun handleStep(step: Step) { - when (step) { - is TransportStep -> { - val neighbors = getTransferableNodes() - val next = neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: neighbors.randomOrNull() ?: return - - // Simply move on to the next node - TransportStep( - step.origin, - step.steps, - next, - step, - step.traversedNodes - ).invoke() - } - - is PowerOriginStep -> { - val neighbors = getTransferableNodes() - val next = neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: neighbors.randomOrNull() ?: return - - // Simply move on to the next node - TransportStep(step, step.steps, next, step, step.traversedNodes).invoke() - } + val next = findClosestOrExit() ?: return + when (step) { + is TransportStep -> TransportStep(step.origin, step.steps, next, step, step.traversedNodes) + is PowerOriginStep -> TransportStep(step, step.steps, next, step, step.traversedNodes) else -> throw NotImplementedError("Unrecognized step type $step") - } + }.invoke() } override fun loadIntoNetwork() { @@ -209,5 +254,4 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode Date: Wed, 15 May 2024 14:17:12 -0500 Subject: [PATCH 061/500] more cleaning --- .../transport/network/ChunkPowerNetwork.kt | 26 +++++-------------- .../node/power/PowerExtractorNode.kt | 17 +++++++++++- .../transport/node/power/SolarPanelNode.kt | 8 ++++++ .../transport/node/type/SourceNode.kt | 6 ++++- .../server/features/transport/step/Step.kt | 2 +- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index a7f8b804a2..7cc591b64d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -14,16 +14,14 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNo import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.step.PowerOriginStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.filterValuesIsInstance import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.atomic.AtomicInteger -import kotlin.math.min class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { override val type: NetworkType = NetworkType.POWER @@ -58,28 +56,17 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( private suspend fun tickSolars() { for (solarPanel in nodes.filterValuesIsInstance().values.distinct()) { - val power = solarPanel.tickAndGetPower() - - if (power <= 0) continue - - runCatching { solarPanel.handleStep(PowerOriginStep(AtomicInteger(), solarPanel, power, mutableSetOf(solarPanel))) }.onFailure { + runCatching { solarPanel.startStep()?.invoke() }.onFailure { IonServer.slF4JLogger.error("Exception ticking solar panel! $it") it.printStackTrace() } } } - private suspend fun tickExtractors() { - for ((_, extractor) in extractors) { - if (!extractor.useful) continue - - val extractablePowerPool = extractor.extractableNodes.flatMap { it.multis } - val sum = extractablePowerPool.sumOf { it.getPower() } - val extractablePower = min(sum, POWER_EXTRACTOR_STEP) - - runCatching { extractor.handleStep(PowerOriginStep(AtomicInteger(), extractor, extractablePower, mutableSetOf(extractor))) }.onFailure { - it.printStackTrace() - } + private suspend fun tickExtractors() = extractors.forEach { (key, extractor) -> + runCatching { extractor.startStep()?.invoke() }.onFailure { + IonServer.slF4JLogger.error("Exception ticking extractor at ${toVec3i(key)}! $it") + it.printStackTrace() } } @@ -115,7 +102,6 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - companion object { const val POWER_EXTRACTOR_STEP = 1000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index e43d94502b..0833a75381 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -15,10 +15,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import java.util.concurrent.atomic.AtomicInteger +import kotlin.math.min import kotlin.properties.Delegates class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, SourceNode { - // The position will always be set override var position by Delegates.notNull() constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { @@ -29,6 +30,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, override val relationships: MutableSet = ObjectOpenHashSet() val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } + /** Whether this node would be useful to extract from this node */ val useful get() = extractableNodes.size >= 1 override fun isTransferableTo(node: TransportNode): Boolean { @@ -80,6 +82,19 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, TransportStep(step, step.steps, next, step, step.traversedNodes).invoke() } + override suspend fun startStep(): PowerOriginStep? { + if (extractableNodes.isEmpty()) return null + + val extractablePowerPool = extractableNodes.flatMap { it.multis } + val sum = extractablePowerPool.sumOf { it.getPower() } + + if (sum == 0) return null + + val extractablePower = min(sum, ChunkPowerNetwork.POWER_EXTRACTOR_STEP) + + return PowerOriginStep(AtomicInteger(), this, extractablePower) + } + override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 29e5b0c075..c52617a4b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -21,6 +21,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LONG_ARRAY +import java.util.concurrent.atomic.AtomicInteger import java.util.function.Consumer import kotlin.math.PI import kotlin.math.max @@ -234,6 +235,13 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, + override val traversedNodes: MutableSet = mutableSetOf(), override val share: Float = 1f ) : Step From 3e719e6f3b567e80b71110891f7e88e55035d5e3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 19 May 2024 19:22:24 -0500 Subject: [PATCH 062/500] extractor & entity changes --- .../server/features/multiblock/Multiblocks.kt | 31 +++---- .../powerbank/new/NewPowerBankMultiblock.kt | 4 +- .../new/NewPowerBankMultiblockTier1.kt | 7 +- .../new/NewPowerBankMultiblockTier2.kt | 6 +- .../new/NewPowerBankMultiblockTier3.kt | 6 +- .../transport/node/power/EndRodNode.kt | 6 +- .../transport/node/power/MergeNode.kt | 6 +- .../node/power/PowerExtractorNode.kt | 26 +++--- .../transport/node/power/PowerFlowMeter.kt | 8 +- .../transport/node/power/PowerInputNode.kt | 37 +++------ .../transport/node/power/SolarPanelNode.kt | 17 ++-- .../transport/node/power/SpongeNode.kt | 6 +- .../transport/node/type/SourceNode.kt | 4 +- .../features/transport/step/PowerStep.kt | 81 +++++++++++++++++++ .../server/features/transport/step/Step.kt | 33 ++++---- 15 files changed, 176 insertions(+), 102 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 450a0120f7..2ee9471f6e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -522,21 +522,22 @@ object Multiblocks : IonServerComponent() { } @EventHandler - fun onPlayerBreakBlock(event: BlockBreakEvent) = multiblockCoroutineScope.launch { - if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return@launch - - val sign = getBukkitBlockState(event.block, false) as? Sign ?: return@launch - - val multiblock = getFromSignPosition( - sign.world, - sign.x, - sign.y, - sign.z, - checkStructure = true, - loadChunks = false - ) ?: return@launch - - removeMultiblock(multiblock, sign) + fun onPlayerBreakBlock(event: BlockBreakEvent) { + if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return + val sign = event.block.state as? Sign ?: return + + runBlocking { //TODO replace this + val multiblock = getFromSignPosition( + sign.world, + sign.x, + sign.y, + sign.z, + checkStructure = true, + loadChunks = false + ) ?: return@runBlocking + + removeMultiblock(multiblock, sign) + } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 20e88637b6..3a82d88342 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -82,8 +82,10 @@ abstract class NewPowerBankMultiblock z: Int, world: World, signDirection: BlockFace, - override val maxPower: Int + override val maxPower: Int, + override var powerUnsafe: Int = 0 ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt index 3969c0bbfb..128afddf9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt @@ -23,13 +23,12 @@ data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock, + multiblock: NewPowerBankMultiblock, x: Int, y: Int, z: Int, world: World, signDirection: BlockFace, - override var powerUnsafe: Int - ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 300_000) - + powerUnsafe: Int + ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 300_000, powerUnsafe) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt index 0993f752bd..98db73c272 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt @@ -23,12 +23,12 @@ data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock, + multiblock: NewPowerBankMultiblock, x: Int, y: Int, z: Int, world: World, signDirection: BlockFace, - override var powerUnsafe: Int - ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 350_000) + powerUnsafe: Int + ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 350_000, powerUnsafe) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt index bb74d37cb8..7233c39240 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt @@ -23,12 +23,12 @@ data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock, + multiblock: NewPowerBankMultiblock, x: Int, y: Int, z: Int, world: World, signDirection: BlockFace, - override var powerUnsafe: Int - ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 500_000_000) + powerUnsafe: Int + ) : PowerBankEntity(multiblock, x, y, z, world, signDirection, 500_000_000, powerUnsafe) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 7b72d11898..8fe90a565d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -8,8 +8,8 @@ import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.PowerTransportStep import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.data.Directional @@ -51,7 +51,7 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } - /** Whether this node would be useful to extract from this node */ - val useful get() = extractableNodes.size >= 1 - override fun isTransferableTo(node: TransportNode): Boolean { if (node is PowerInputNode) return false return node !is SourceNode @@ -74,25 +72,33 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, override suspend fun handleStep(step: Step) { // Nothing can transfer to extractors - step as PowerOriginStep + step as PowerExtractorOriginStep val next = getTransferableNodes().randomOrNull() ?: return // Simply move on to the next node - TransportStep(step, step.steps, next, step, step.traversedNodes).invoke() + PowerTransportStep(step, step.steps, next, step, step.traversedNodes).invoke() } - override suspend fun startStep(): PowerOriginStep? { + var lastTicked: Long = System.currentTimeMillis() + + override suspend fun startStep(): PowerExtractorOriginStep? { if (extractableNodes.isEmpty()) return null + val limit = getTransferPower() + val extractablePowerPool = extractableNodes.flatMap { it.multis } val sum = extractablePowerPool.sumOf { it.getPower() } if (sum == 0) return null - val extractablePower = min(sum, ChunkPowerNetwork.POWER_EXTRACTOR_STEP) + val extractablePower = min(sum, limit) + + return PowerExtractorOriginStep(AtomicInteger(), this, extractablePower, extractablePowerPool) + } - return PowerOriginStep(AtomicInteger(), this, extractablePower) + fun getTransferPower(): Int { + return (ChunkPowerNetwork.POWER_EXTRACTOR_STEP * ((System.currentTimeMillis() - lastTicked) / 2000.0)).roundToInt() } override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 5d864e84b7..96c3129530 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.PowerTransportStep import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component @@ -39,7 +39,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { override suspend fun handleStep(step: Step) { // This is not an origin node, so we can assume that it is not an origin step - step as TransportStep + step as PowerTransportStep val next = getTransferableNodes() .filterNot { step.traversedNodes.contains(it) } @@ -47,7 +47,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { .randomOrNull() ?: return // Simply move on to the next node - TransportStep( + PowerTransportStep( step.origin, step.steps, next, @@ -62,7 +62,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { private val averages = mutableListOf() override suspend fun onCompleteChain(final: Step, destination: PowerInputNode, transferred: Int) { - final as TransportStep + final as PowerTransportStep addAverage(TransferredPower(transferred, System.currentTimeMillis())) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 2f9789dd55..70e6ee2dbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.step.PowerTransportStep import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -17,8 +17,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import kotlin.math.floor -import kotlin.math.min import kotlin.properties.Delegates class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { @@ -72,46 +70,31 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { step.traversedNodes.add(this) // This is not an origin node, so we can assume that it is not an origin step - step as TransportStep + step as PowerTransportStep val origin = step.origin val multi = multis.randomOrNull() ?: return - val share = floor(origin.power * step.share).toInt() + val room = multi.maxPower - multi.getPower() + val power = origin.finishExtraction(step, room) - origin.power -= share + println("Finished extraction, returned $power power") - multi.addPower(share) - - var remaining = share - - if (origin.currentNode is PowerExtractorNode) { - for (extractable in origin.currentNode.extractableNodes.flatMap { it.multis }) { - val toTake = min(remaining, extractable.getPower()) - - remaining -= toTake - extractable.removePower(toTake) - - if (remaining <= 0) break - } - } + multi.addPower(power) // println("Traversed nodes: ${step.traversedNodes}") step.traversedNodes.forEach { - it.onCompleteChain(step, this, share) + it.onCompleteChain(step, this, power) } - if (step.origin.currentNode is SolarPanelNode) return - -// println(""" +// if (step.origin.currentNode is SolarPanelNode) return // +// println(""" // Reached multiblock input // Origin: $origin // // Selected $multi -// Added $share to $multi -// Remaining origin power: ${origin.power} -// +// Added $power to $multi // """.trimIndent()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index c52617a4b2..b82fdac2c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -8,9 +8,9 @@ import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerOriginStep +import net.horizonsend.ion.server.features.transport.step.PowerTransportStep +import net.horizonsend.ion.server.features.transport.step.SolarPowerOriginStep import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.TransportStep import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -71,6 +71,7 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode TransportStep(step.origin, step.steps, next, step, step.traversedNodes) - is PowerOriginStep -> TransportStep(step, step.steps, next, step, step.traversedNodes) + is PowerTransportStep -> PowerTransportStep(step.origin, step.steps, next, step, step.traversedNodes) + is SolarPowerOriginStep -> PowerTransportStep(step, step.steps, next, step, step.traversedNodes) else -> throw NotImplementedError("Unrecognized step type $step") }.invoke() } - override suspend fun startStep(): PowerOriginStep? { + override suspend fun startStep(): SolarPowerOriginStep? { val power = tickAndGetPower() if (power <= 0) return null - return PowerOriginStep(AtomicInteger(), this, power) +// println("Starting solar step") + + return SolarPowerOriginStep(AtomicInteger(), this, power) } override fun loadIntoNetwork() { @@ -261,5 +264,5 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, + override val traversedNodes: MutableSet = mutableSetOf(), +) : OriginStep { + override fun finishExtraction(final: TransportStep, amount: Int): Int { + if (extractable.isEmpty()) return 0 + + // Store multis that still have power + val toExtract = extractable.toMutableList() + + // The share of the origin power along this branch of the chain + val share = (final.share * maxPower).roundToInt() + + // The maximum that should be extracted + // If limited, pick the lower + val maxPower = min(amount, share) + + // Remaining power to take + var remaining = maxPower + + // Take as much as possible + while (remaining >= 0) { + // Shouldn't be null but + val nextMin = toExtract.minByOrNull { it.getPower() } ?: return 0 + + // Take an equal amount from all multis so that the first is drained + val minTake = min(remaining, nextMin.getPower() * toExtract.size) + + // Remove this amount from remaining + remaining -= minTake + + // Perform the drain + extractEqually(minTake) + + toExtract.remove(nextMin) + } + + return maxPower - remaining + } + + /** + * Extract an equal amount of power from the extractable power banks + **/ + private fun extractEqually(amount: Int) { + val n = extractable.size + + extractable.forEach { + it.removePower(amount / n) + } + } +} + +data class SolarPowerOriginStep( + override val steps: AtomicInteger, + override val currentNode: TransportNode, + val power: Int, + override val traversedNodes: MutableSet = mutableSetOf(), +) : OriginStep { + // Solar panels do not have any additional logic needed upon extraction + override fun finishExtraction(final: TransportStep, amount: Int): Int = amount +} + +data class PowerTransportStep( + val origin: OriginStep, + override val steps: AtomicInteger, + override val currentNode: TransportNode, + val previous: Step, + override val traversedNodes: MutableSet, + override val share: Float = 1f +) : TransportStep diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index e10d5f01e2..70906f022f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -6,7 +6,6 @@ import java.util.concurrent.atomic.AtomicInteger interface Step { val steps: AtomicInteger val currentNode: TransportNode - val share: Float val traversedNodes: MutableSet suspend operator fun invoke() { @@ -29,19 +28,19 @@ interface Step { } } -data class PowerOriginStep( - override val steps: AtomicInteger, - override val currentNode: TransportNode, - var power: Int, - override val traversedNodes: MutableSet = mutableSetOf(), - override val share: Float = 1f -) : Step - -data class TransportStep( - val origin: PowerOriginStep, - override val steps: AtomicInteger, - override val currentNode: TransportNode, - val previous: Step, - override val traversedNodes: MutableSet, - override val share: Float = 1f -) : Step +/** + * A step that is the first in a chain + **/ +interface OriginStep : Step { + /** + * Removes the appropriate amount of power. Returns the amount that was removed (and is available) + * + * @param final The final step of the chain + * @param amount The limit of extraction (will use either this value or the maximum amount defined in this config, whichever is lower) + **/ + fun finishExtraction(final: TransportStep, amount: Int): Int +} + +interface TransportStep : Step { + val share: Float +} From f2279ff4374350d171f8dfe31be07f99149c128d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 3 Jun 2024 22:41:33 -0500 Subject: [PATCH 063/500] move new multiblock code to separate file for now --- .../command/starship/StarshipsCommand.kt | 6 +- .../features/ai/spawning/AISpawningUtils.kt | 2 - .../features/multiblock/MultiblockShape.kt | 4 +- .../server/features/multiblock/Multiblocks.kt | 2 + .../multiblock/crafting/MultiblockRecipes.kt | 169 ++++++++++++++++++ .../crafting/ingredient/Consumable.kt | 2 +- .../ingredient/ConsumedItemIngredient.kt | 2 +- .../ingredient/GasCanisterIngredient.kt | 2 +- .../crafting/ingredient/ItemConsumable.kt | 2 +- .../crafting/ingredient/ItemIngredient.kt | 2 +- .../ingredient/MultiblockRecipeIngredient.kt | 2 +- .../ProgressHolderItemIngredient.kt | 2 +- .../crafting/ingredient/ResourceIngredient.kt | 2 +- .../crafting/recipe/FurnaceEventHandler.kt | 2 +- .../recipe/FurnaceMultiblockRecipe.kt | 2 +- .../crafting/recipe/MultiblockRecipe.kt | 4 +- .../recipe/ProcessingMultiblockRecipe.kt | 4 +- .../crafting/result/ActionResult.kt | 2 +- .../{type => }/crafting/result/ItemResult.kt | 2 +- .../crafting/result/MultiRecipeResult.kt | 0 .../crafting/result/MultiblockRecipeResult.kt | 0 .../crafting/result/ProgressItemResult.kt | 2 +- .../crafting/result/ResourceResult.kt | 0 .../{type => }/crafting/result/SoundResult.kt | 0 .../multiblock/newer/MultiblockEntities.kt | 15 ++ .../multiblock/newer/NewMultiblocks.kt | 46 +++++ .../multiblock/type/FurnaceMultiblock.kt | 2 +- .../type/ammo/MissileLoaderMultiblock.kt | 2 +- .../type/crafting/MultiblockRecipes.kt | 4 +- .../crafting/ingredient/MatchingIngredient.kt | 24 --- .../type/industry/CircuitfabMultiblock.kt | 1 - .../turret/IonTurretMultiblock.kt | 3 +- .../features/multiblock/util/BlockSnapshot.kt | 4 +- .../starship/active/SubsystemDetector.kt | 2 +- .../primary/IonTurretWeaponSubsystem.kt | 2 +- 35 files changed, 262 insertions(+), 60 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/Consumable.kt (68%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/ConsumedItemIngredient.kt (87%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/GasCanisterIngredient.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/ItemConsumable.kt (74%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/ItemIngredient.kt (85%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/MultiblockRecipeIngredient.kt (76%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/ProgressHolderItemIngredient.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/ingredient/ResourceIngredient.kt (90%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/recipe/FurnaceEventHandler.kt (74%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/recipe/FurnaceMultiblockRecipe.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/recipe/MultiblockRecipe.kt (69%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/recipe/ProcessingMultiblockRecipe.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/ActionResult.kt (81%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/ItemResult.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/MultiRecipeResult.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/MultiblockRecipeResult.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/ProgressItemResult.kt (95%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/ResourceResult.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type => }/crafting/result/SoundResult.kt (100%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MatchingIngredient.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipsCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipsCommand.kt index f70dd24de4..4aae3f1fbd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipsCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipsCommand.kt @@ -20,9 +20,9 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.starship.PilotedStarships import net.horizonsend.ion.server.miscellaneous.utils.actualType -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.empty diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt index 5fe8f27a19..256495a81c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt @@ -17,8 +17,6 @@ import net.horizonsend.ion.server.features.starship.active.ActiveControlledStars import net.horizonsend.ion.server.features.starship.control.controllers.Controller import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.modules.AISinkMessageFactory -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt index 4b2f798265..4e8eb4aed4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt @@ -2,14 +2,12 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.multiblock.util.awaitAllValues -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BARGE_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield10.buildStructure +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.features.transport.Wires import net.horizonsend.ion.server.features.transport.pipe.Pipes diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 2ee9471f6e..714ae58782 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -297,6 +297,8 @@ object Multiblocks : IonServerComponent() { registerMultiblock(MiningLaserMultiblockTier4Top) registerMultiblock(MiningLaserMultiblockTier4Bottom) registerMultiblock(MiningLaserMultiblockTier4Side) + registerMultiblock(TopArsenalStarshipWeaponMultiblock) + registerMultiblock(BottomArsenalStarshipWeaponMultiblock) registerMultiblock(ItemSplitterMultiblock) registerMultiblock(GasCollectorMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt new file mode 100644 index 0000000000..55b56af563 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt @@ -0,0 +1,169 @@ +package net.horizonsend.ion.server.features.multiblock.crafting + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ConsumedItemIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.GasCanisterIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ProgressHolderItemIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.ProcessingMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiRecipeResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.SoundResult +import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.Material +import org.bukkit.SoundCategory +import org.bukkit.block.Sign +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack +import java.util.LinkedList +import java.util.concurrent.ConcurrentHashMap + +@Suppress("UNUSED") +object MultiblockRecipes : IonServerComponent() { + private val recipes: ConcurrentHashMap>> = ConcurrentHashMap() + + val URANIUM_ENRICHMENT = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = CentrifugeMultiblock, + smelting = ConsumedItemIngredient(CustomItems.URANIUM, 1), + result = MultiRecipeResult( + ItemResult(CustomItems.ENRICHED_URANIUM), + SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + ) + ) + + val URANIUM_CORE_COMPRESSION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = CompressorMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.URANIUM_CORE, 1), progressHolderResult = CustomItems.URANIUM_ROD), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = MultiRecipeResult( + ProgressItemResult(CustomItems.URANIUM_ROD, 60L * 60L * 20L, SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + ) + + val STEEL_PRODUCTION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + FurnaceMultiblockRecipe( + multiblock = GasFurnaceMultiblock, + smelting = ConsumedItemIngredient(ItemStack(Material.IRON_INGOT), 1), + fuel = GasCanisterIngredient(CustomItems.GAS_CANISTER_OXYGEN, 5), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ItemResult(CustomItems.STEEL_INGOT) + ) + ) + + val REACTIVE_PLATING_PRESSING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = PlatePressMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.REACTIVE_PLATING, 1), progressHolderResult = CustomItems.REACTIVE_CHASSIS), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.REACTIVE_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val STEEL_PLATE_PRESSING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = PlatePressMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.STEEL_PLATE, 1), progressHolderResult = CustomItems.STEEL_CHASSIS), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.STEEL_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val FUEL_ROD_CORE_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = FabricatorMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.FUEL_ROD_CORE, 1), progressHolderResult = CustomItems.FUEL_CELL), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.FUEL_CELL, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val FABRICATED_ASSEMBLY_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = FabricatorMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.REACTIVE_ASSEMBLY, 1), progressHolderResult = CustomItems.FABRICATED_ASSEMBLY), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.FABRICATED_ASSEMBLY, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val REINFORCED_FRAME_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = FabricatorMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.STEEL_ASSEMBLY, 1), progressHolderResult = CustomItems.REINFORCED_FRAME), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.REINFORCED_FRAME, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val CIRCUIT_BOARD_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = CircuitfabMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.CIRCUITRY, 1), progressHolderResult = CustomItems.CIRCUIT_BOARD), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.CIRCUIT_BOARD, 60L * 60L * 20L, SoundResult("horizonsend:industry.cirfab", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val LOADED_SHELL_LOADING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = AmmoLoaderMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNLOADED_SHELL, 1), progressHolderResult = CustomItems.LOADED_SHELL), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = MultiRecipeResult(ProgressItemResult(CustomItems.LOADED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f))) + ) + ) + + val UNCHARGED_SHELL_CHARGING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = AmmoLoaderMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNCHARGED_SHELL, 1), progressHolderResult = CustomItems.CHARGED_SHELL), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.CHARGED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + val ARSENAL_MISSILE_LOADING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + ProcessingMultiblockRecipe( + multiblock = MissileLoaderMultiblock, + smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNLOADED_ARSENAL_MISSILE, 1), progressHolderResult = CustomItems.ARSENAL_MISSILE), + resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + result = ProgressItemResult(CustomItems.ARSENAL_MISSILE, 60L * 60L * 20L, SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f)) + ) + ) + + /** + * Add a power ingredient + **/ + private fun power(amount: Int) = ResourceIngredient(NamespacedKeys.POWER, amount) + + private fun registerRecipe(recipe: MultiblockRecipe): MultiblockRecipe { + net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.recipes.getOrPut(recipe.multiblock) { LinkedList() }.add(recipe) + + return recipe + } + + fun getRecipe(multiblock: T, sign: Sign, inventory: Inventory): MultiblockRecipe? { + @Suppress("UNCHECKED_CAST") + val recipesFor = (net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.recipes[multiblock] as? LinkedList>) ?: return null + + return recipesFor.firstOrNull { it.matches(sign, inventory) } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/Consumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt similarity index 68% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/Consumable.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt index 8d9ae7dddb..258fbb35a5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/Consumable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.multiblock.Multiblock import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ConsumedItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt similarity index 87% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ConsumedItemIngredient.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt index 7c77cde309..3bd6420e9e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ConsumedItemIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/GasCanisterIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/GasCanisterIngredient.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt index 1813f392cf..b07f582741 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/GasCanisterIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.GasCanister diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ItemConsumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt similarity index 74% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ItemConsumable.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt index 016a1e4218..ee28313fa8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ItemConsumable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.multiblock.Multiblock import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ItemIngredient.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt index 55b867d814..beadd9455b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ItemIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.multiblock.Multiblock import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MultiblockRecipeIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt similarity index 76% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MultiblockRecipeIngredient.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt index 02ff940f32..d8d697df66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MultiblockRecipeIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.multiblock.Multiblock import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ProgressHolderItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ProgressHolderItemIngredient.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt index 2f6a71eb08..2c285c2c17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ProgressHolderItemIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ResourceIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ResourceIngredient.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt index 493f10661b..9739c92fc2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/ResourceIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.machine.PowerMachines.getPower import net.horizonsend.ion.server.features.machine.PowerMachines.removePower diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceEventHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt similarity index 74% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceEventHandler.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt index 4fb2974374..7700835a88 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceEventHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.recipe +package net.horizonsend.ion.server.features.multiblock.crafting.recipe import org.bukkit.block.Furnace import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt index d1792b70f8..8073a5ad0b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.recipe +package net.horizonsend.ion.server.features.multiblock.crafting.recipe import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemConsumable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/MultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/MultiblockRecipe.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt index 6f76b1c178..8965039182 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/MultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.recipe +package net.horizonsend.ion.server.features.multiblock.crafting.recipe import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.crafting.result.MultiblockRecipeResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult import org.bukkit.block.Sign import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt index bfdfb82a48..651166223d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/recipe/ProcessingMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.recipe +package net.horizonsend.ion.server.features.multiblock.crafting.recipe import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemConsumable import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult +import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt similarity index 81% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt index 379b761939..715fe2ceb7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ActionResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt index cba7730ba0..a5b2cad451 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiRecipeResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiblockRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/MultiblockRecipeResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt index ba8e0681a2..da39407f7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ProgressItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.result +package net.horizonsend.ion.server.features.multiblock.crafting.result import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ResourceResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ResourceResult.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/ResourceResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ResourceResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/SoundResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/result/SoundResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt new file mode 100644 index 0000000000..dfc02b58f3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.multiblock.newer + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity + +object MultiblockEntities { + private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + + fun T.executeAsync(block: suspend () -> Unit) { + multiblockCoroutineScope.launch { block.invoke() } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt new file mode 100644 index 0000000000..3765c4c90f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt @@ -0,0 +1,46 @@ +package net.horizonsend.ion.server.features.multiblock.newer + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock +import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier3 + +//TODO store the progress of migrated multiblocks here +object NewMultiblocks : IonServerComponent() { + private val multiblocks: MutableMap = mutableMapOf() + private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + + override fun onEnable() { + initMultiblocks() + + log.info("Loaded ${multiblocks.size} multiblocks") + } + + private fun initMultiblocks() { + registerMultiblock(TestMultiblock) + registerMultiblock(NewPowerBankMultiblockTier1) + registerMultiblock(NewPowerBankMultiblockTier2) + registerMultiblock(NewPowerBankMultiblockTier3) + } + + private fun registerMultiblock(multiblock: Multiblock) { + val name = multiblock.javaClass.simpleName ?: throw IllegalArgumentException("Provided anonymous multiblock class!") + + if (multiblocks.containsKey(name)) { + throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[name]}, new: $multiblock") + } + + multiblocks[name] = multiblock + } + + fun setMultiblock(x: Int, y: Int, z: Int) { + + } + + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt index ced1b557d8..1e8b071724 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceEventHandler import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes -import net.horizonsend.ion.server.features.multiblock.type.crafting.recipe.FurnaceEventHandler import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index e29454587d..6eb6ed7b27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt index 2d32617fc0..c290977f4e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt @@ -3,8 +3,6 @@ package net.horizonsend.ion.server.features.multiblock.crafting import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ConsumedItemIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.GasCanisterIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ProgressHolderItemIngredient @@ -16,6 +14,8 @@ import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiRecipeResult import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressItemResult import net.horizonsend.ion.server.features.multiblock.crafting.result.SoundResult +import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MatchingIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MatchingIngredient.kt deleted file mode 100644 index 93c11ad4ad..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/ingredient/MatchingIngredient.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.crafting.ingredient - -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.miscellaneous.utils.getMatchingMaterials -import org.bukkit.Material -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack - -open class MatchingIngredient(val match: String, val ignore : Set, val amount: Int) : MultiblockRecipeIngredient { - val matches = run { - val list: MutableSet = getMatchingMaterials { it.name.matches(Regex(match)) } - list.removeAll(ignore) - list.toSet() - } - - override fun checkRequirement(multiblock: Multiblock, sign: Sign, itemStack: ItemStack?): Boolean { - if (itemStack == null) return false - matches.any() - - if (matches.any{!itemStack.isSimilar(ItemStack(it))}) return false - - return itemStack.amount >= amount - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt index 597b713791..7c791c2985 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt @@ -8,7 +8,6 @@ import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent - object CircuitfabMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { override val name = "circuitfab" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt index d2de379a4f..21dd15f615 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt @@ -1,8 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt index da05bcf3d3..49e327c567 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.util import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.features.customblocks.CustomBlock -import net.horizonsend.ion.server.features.customblocks.CustomBlocks +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import org.bukkit.Bukkit import org.bukkit.ChunkSnapshot import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index 516eb4f544..4c9cda2ba4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -6,10 +6,10 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.misc.FuelTankMultiblock +import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt index 5dc57c46d7..f4c82bfaca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.starshipweapon.turret.IonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.IonTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem From 6aa2aa6052d87caa4d08832a19e1a1ab55c2c1e1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 18 Jun 2024 14:35:07 -0500 Subject: [PATCH 064/500] start rebuild of multiblock access --- .../multiblock/newer/MultiblockAccess.kt | 125 ++++++++++++++++++ .../newer/MultiblockDetectedEvent.kt | 7 + ...ltiblocks.kt => MultiblockRegistration.kt} | 8 +- .../multiblock/type/SignMultiblock.kt | 4 + .../utils/coordinates/Coordinates.kt | 2 + 5 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/{NewMultiblocks.kt => MultiblockRegistration.kt} (94%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt new file mode 100644 index 0000000000..6f20790524 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -0,0 +1,125 @@ +package net.horizonsend.ion.server.features.multiblock.newer + +import com.google.common.cache.CacheBuilder +import com.google.common.cache.CacheLoader +import com.google.common.cache.LoadingCache +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.event.EventHandler +import org.bukkit.event.world.WorldUnloadEvent +import java.util.Optional +import java.util.concurrent.TimeUnit +import kotlin.jvm.optionals.getOrNull + +object MultiblockAccess : IonServerComponent() { + private val multiblockCache: MutableMap, Optional>> = mutableMapOf() + + /** + * Access or compute the multiblock at a world position + * + * The position provided should be the origin position, not the sign position + **/ + fun getCachedMultiblock(world: World, x: Int, y: Int, z: Int, face: BlockFace): Multiblock? { + return multiblockCache.getOrPut(world) { + CacheBuilder + .newBuilder() + .weakKeys() + .expireAfterWrite(1, TimeUnit.MINUTES) + .build(CacheLoader.from { (location, face) -> + return@from Optional.ofNullable(computeMultiblockAtLocation(world, location.x, location.y, location.z, face)) + }) + }[Vec3i(x, y, z) to face].getOrNull() + } + + private fun computeMultiblockAtLocation(world: World, x: Int, y: Int, z: Int, face: BlockFace?, loadChunks: Boolean = false): Multiblock? { + // Will only return null if not loaded and don't load chunks + val originBlock = if (loadChunks) world.getBlockAt(x, y, z) else getBlockIfLoaded(world, x, y, z) ?: return null + + for ((_, multiblock) in MultiblockRegistration.getAllMultiblocks()) { + // If provided a face, check only it + if (face != null) { + if (!multiblock.blockMatchesStructure(originBlock, face, loadChunks, false)) continue + } + // If no face is provided, e.g. no sign available to reference, check every side + else if (CARDINAL_BLOCK_FACES.none { + multiblock.blockMatchesStructure(originBlock, it, loadChunks, false) + }) continue + + return multiblock + } + + return null + } + + /** + * Attempt to get the multiblock at the location provided + * + * The position provided should be the origin position, not the sign position + **/ + fun getMultiblock(world: World, x: Int, y: Int, z: Int, face: BlockFace, checkStructure: Boolean, loadChunks: Boolean = false): Multiblock? { + // Will only return null if not loaded and don't load chunks + val originBlock = if (loadChunks) world.getBlockAt(x, y, z) else getBlockIfLoaded(world, x, y, z) ?: return null + + val cached = getCachedMultiblock(world, x, y, z, face) + + if (cached != null) { + if (!checkStructure) return cached + + return cached.takeIf { + cached.blockMatchesStructure(originBlock, face, loadChunks, false) + } + } + + if (!loadChunks || !checkStructure) return null + + // If the cache didn't compute it, there's a chance it wasn't loaded. In that case, compute again and load chunks, if requested. + return computeMultiblockAtLocation(world, x, y, z, face, true) + } + + fun setMultiblock(world: World, x: Int, y: Int, z: Int, face: BlockFace, multiblock: Multiblock): Boolean { + if (multiblock is SignMultiblock) { + val signOffset = face.oppositeFace + val signLoc = Vec3i(x, y, z).getRelative(signOffset) + val sign = getBlockIfLoaded(world, signLoc.x, signLoc.y, signLoc.z)?.state as? Sign ?: return false + + + } + + if (multiblock is EntityMultiblock<*>) { + + } + + return true + } + + /** + * Remove this multiblock & entity, provided the multiblock origin + **/ + fun removeMultiblock(world: World, x: Int, y: Int, z: Int, facing: BlockFace) { + //TODO remove multiblock entity + multiblockCache[world]?.invalidate(Vec3i(x, y, z) to facing) + } + + fun tryDetectMultiblock(x: Int, y: Int, z: Int) { + + } + + fun tryDetectMultiblock(x: Int, y: Int, z: Int) { + + } + + @EventHandler + fun onWorldUnload(event: WorldUnloadEvent) { + val cache = multiblockCache.remove(event.world) ?: return + cache.invalidateAll() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt new file mode 100644 index 0000000000..c3f6add82b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.multiblock.newer + +import org.bukkit.event.Cancellable +import org.bukkit.event.player.PlayerEvent + +class MultiblockDetectedEvent(): PlayerEvent, Cancellable { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 3765c4c90f..9dff6af936 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/NewMultiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowe import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier3 //TODO store the progress of migrated multiblocks here -object NewMultiblocks : IonServerComponent() { +object MultiblockRegistration : IonServerComponent() { private val multiblocks: MutableMap = mutableMapOf() private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) @@ -38,9 +38,5 @@ object NewMultiblocks : IonServerComponent() { multiblocks[name] = multiblock } - fun setMultiblock(x: Int, y: Int, z: Int) { - - } - - + fun getAllMultiblocks() = multiblocks } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt new file mode 100644 index 0000000000..0a1bb4b068 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.multiblock.type + +interface SignMultiblock { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt index 158910ef43..3b5d4e1677 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt @@ -567,3 +567,5 @@ fun Location.getLocationNear(minDistance: Double, maxDistance: Double): Location } fun Vec3i.toChunkLocal(): Vec3i = Vec3i(x % 16, y, z % 16) + +fun Vec3i.getRelative(direction: BlockFace, distance: Int = 1) = plus(Vec3i(direction.modX * distance, direction.modY * distance, direction.modZ * distance)) From 811fcb885ddb19150e531b92914ac044d7696fa0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 19 Jun 2024 18:58:50 -0500 Subject: [PATCH 065/500] finish new multiblock detection --- .../multiblock/ChunkMultiblockManager.kt | 6 +- .../server/features/multiblock/Multiblocks.kt | 23 --- .../entity/PersistentMultiblockData.kt | 5 +- .../multiblock/newer/MultiblockAccess.kt | 156 +++++++++++++++++- .../newer/MultiblockDetectedEvent.kt | 7 +- .../multiblock/newer/MultiblockEntities.kt | 41 +++++ .../newer/MultiblockRegistration.kt | 23 +++ .../powerbank/new/NewPowerBankMultiblock.kt | 3 +- .../features/transport/node/NodeType.kt | 2 + .../transport/node/power/MergeNode.kt | 6 +- .../transport/node/power/PowerInputNode.kt | 2 +- .../transport/node/power/PowerNodeFactory.kt | 6 +- .../features/world/chunk/ChunkRegion.kt | 2 + .../miscellaneous/registrations/Components.kt | 4 + 14 files changed, 238 insertions(+), 48 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 301870236a..956cff3e96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -150,11 +150,13 @@ class ChunkMultiblockManager(val chunk: IonChunk) { /** * Upon the removal of a multiblock sign **/ - fun removeMultiblockEntity(x: Int, y: Int, z: Int) { + fun removeMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { val key = toBlockKey(x, y, z) - multiblockEntities.remove(key) + val entity = multiblockEntities.remove(key) tickingMultiblockEntities.remove(key) + + return entity } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 714ae58782..635ac09e5e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -80,7 +80,6 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblo import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic @@ -98,9 +97,6 @@ import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMu import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerCellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier3 @@ -109,7 +105,6 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinter import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock @@ -330,10 +325,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(CruiserReactorMultiblock) registerMultiblock(BargeReactorMultiBlock) registerMultiblock(OdometerMultiblock) - registerMultiblock(TestMultiblock) - registerMultiblock(NewPowerBankMultiblockTier1) - registerMultiblock(NewPowerBankMultiblockTier2) - registerMultiblock(NewPowerBankMultiblockTier3) } private fun registerMultiblock(multiblock: Multiblock) { @@ -560,18 +551,6 @@ object Multiblocks : IonServerComponent() { sign.isWaxed = true sign.update() - - if (multiblock is EntityMultiblock<*>) { - // Multiblock entities are stored inside the block that the sign is placed on - val (x, _, z) = Multiblock.getOrigin(sign) - - val chunkX = x.shr(4) - val chunkZ = z.shr(4) - - val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - - multiblockCoroutineScope.launch { chunk.multiblockManager.addNewMultiblockEntity(multiblock, sign) } - } } /** Upon a multiblock being removed */ @@ -582,7 +561,5 @@ object Multiblocks : IonServerComponent() { val chunkZ = z.shr(4) val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - - chunk.multiblockManager.removeMultiblockEntity(x, y, z) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index 991d2832b9..71b2c60a1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ADDITIONAL_MULTIBLOCK_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_SIGN_OFFSET @@ -57,7 +57,8 @@ class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Mul val signDirectionString = primitive.get(MULTIBLOCK_SIGN_OFFSET, STRING)!! val signDirection = BlockFace.valueOf(signDirectionString) - val multiblockType = Multiblocks.all().firstOrNull { it::class.simpleName == primitive.get(MULTIBLOCK, STRING) }!! + val rawType = primitive.get(MULTIBLOCK, STRING) ?: throw NullPointerException("Stored multiblock data did not have multiblock type!") + val multiblockType = MultiblockRegistration.getByStorageName(rawType) ?: throw SerializationException("Error deserializing multiblock data! Multiblock $rawType does not exist!") val additionalData = primitive.get(ADDITIONAL_MULTIBLOCK_DATA, TAG_CONTAINER)!! diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 6f20790524..c9386a4d16 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -3,19 +3,42 @@ package net.horizonsend.ion.server.features.multiblock.newer import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.success +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.plainText +import net.horizonsend.ion.common.utils.text.subStringBetween import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.getMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.removeMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.setMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.isSign import org.bukkit.World +import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.entity.Player import org.bukkit.event.EventHandler +import org.bukkit.event.block.Action +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.world.WorldUnloadEvent +import org.bukkit.inventory.EquipmentSlot +import org.bukkit.persistence.PersistentDataType import java.util.Optional import java.util.concurrent.TimeUnit import kotlin.jvm.optionals.getOrNull @@ -40,11 +63,26 @@ object MultiblockAccess : IonServerComponent() { }[Vec3i(x, y, z) to face].getOrNull() } - private fun computeMultiblockAtLocation(world: World, x: Int, y: Int, z: Int, face: BlockFace?, loadChunks: Boolean = false): Multiblock? { + /** + * Finds the first multiblock that can be detected at the position. + * + * If the block face provided is null, every block face will be checked + * + * @return the multiblock found, or null + **/ + private fun computeMultiblockAtLocation( + world: World, + x: Int, + y: Int, + z: Int, + face: BlockFace?, + loadChunks: Boolean = false, + restrictedList: Collection = MultiblockRegistration.getAllMultiblocks().values + ): Multiblock? { // Will only return null if not loaded and don't load chunks val originBlock = if (loadChunks) world.getBlockAt(x, y, z) else getBlockIfLoaded(world, x, y, z) ?: return null - for ((_, multiblock) in MultiblockRegistration.getAllMultiblocks()) { + for (multiblock in restrictedList) { // If provided a face, check only it if (face != null) { if (!multiblock.blockMatchesStructure(originBlock, face, loadChunks, false)) continue @@ -85,17 +123,50 @@ object MultiblockAccess : IonServerComponent() { return computeMultiblockAtLocation(world, x, y, z, face, true) } - fun setMultiblock(world: World, x: Int, y: Int, z: Int, face: BlockFace, multiblock: Multiblock): Boolean { + /** + * Handle the setup and creation of the multiblock. Assumes structure has already been checked. + * + * @return if the multiblock could be created properly. + **/ + fun setMultiblock(detector: Player, world: World, x: Int, y: Int, z: Int, face: BlockFace, multiblock: Multiblock): Boolean { if (multiblock is SignMultiblock) { val signOffset = face.oppositeFace val signLoc = Vec3i(x, y, z).getRelative(signOffset) val sign = getBlockIfLoaded(world, signLoc.x, signLoc.y, signLoc.z)?.state as? Sign ?: return false + Tasks.sync { + sign.persistentDataContainer.set( + NamespacedKeys.MULTIBLOCK, + PersistentDataType.STRING, + multiblock.javaClass.simpleName + ) + + sign.isWaxed = true + + println("Setting up") + multiblock.setupSign(detector, sign) + + sign.update(false, false) + } } if (multiblock is EntityMultiblock<*>) { + val present = getMultiblockEntity(world, x, y, z) + if (present != null) { + log.warn("Attempted to place multiblock entity where one was already present!") + } + + // Create blank multiblock entity + setMultiblockEntity(world, x, y, z, multiblock.createEntity( + PersistentMultiblockData(x, y, z, multiblock, face), + world, + x, + y, + z, + face + )) } return true @@ -104,17 +175,54 @@ object MultiblockAccess : IonServerComponent() { /** * Remove this multiblock & entity, provided the multiblock origin **/ - fun removeMultiblock(world: World, x: Int, y: Int, z: Int, facing: BlockFace) { - //TODO remove multiblock entity + fun removeMultiblock(world: World, x: Int, y: Int, z: Int, facing: BlockFace): Multiblock? { + val removed = removeMultiblockEntity(world, x, y, z) multiblockCache[world]?.invalidate(Vec3i(x, y, z) to facing) + return removed?.multiblock } - fun tryDetectMultiblock(x: Int, y: Int, z: Int) { + /** + * Handle the identification, detection and setup of the multiblock, if one is present at the location. + * + * @return the detected multiblock, if found + **/ + fun tryDetectMultiblock(player: Player, sign: Sign, loadChunks: Boolean = false): Multiblock? { + val signLoc = Vec3i(sign.location) + val world = sign.world + + val blankText = sign.front().line(0).plainText() + val name = blankText.subStringBetween('[', ']') - } + val direction = sign.getFacing().oppositeFace + + // Get the block that the sign is placed on + val originBlock = signLoc.getRelative(direction, 1) + val (x, y, z) = originBlock + + // Possible multiblocks from the sign + val possible = MultiblockRegistration.getBySignName(name) + + val found = computeMultiblockAtLocation( + world, + x, + y, + z, + null, + loadChunks = loadChunks, + restrictedList = possible + ) - fun tryDetectMultiblock(x: Int, y: Int, z: Int) { + if (found == null) { + player.userError("Improperly built $name. Make sure every block is correctly placed!") + MultiblockCommand.setupCommand(player, sign, possible.first()) + + return null + } + + setMultiblock(player, world, x, y, z, direction, found) + + return found } @EventHandler @@ -122,4 +230,36 @@ object MultiblockAccess : IonServerComponent() { val cache = multiblockCache.remove(event.world) ?: return cache.invalidateAll() } + + @EventHandler + fun onPlayerInteract(event: PlayerInteractEvent) { + if (event.hand != EquipmentSlot.HAND || event.action != Action.RIGHT_CLICK_BLOCK) return + + val clickedBlock = event.clickedBlock ?: return + val sign = clickedBlock.state as? Sign ?: return + + if (sign.persistentDataContainer.has(NamespacedKeys.MULTIBLOCK)) return + + val result = tryDetectMultiblock(event.player, sign, false) + + if (result != null) { + event.player.success("Detected new ${result.name}") + } + } + + @EventHandler + fun onPlayerBreakBlock(event: BlockBreakEvent) { + if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return + val sign = event.block.state as? Sign ?: return + + val origin = sign.getMultiblockOrigin() + + val removed = removeMultiblock(event.block.world, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) ?: return + + event.player.information("Destroyed ${removed.name}") + } + + fun Sign.getMultiblockOrigin(): Block { + return block.getRelative(getFacing().oppositeFace, 1) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt index c3f6add82b..df481eb6ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt @@ -1,7 +1,4 @@ package net.horizonsend.ion.server.features.multiblock.newer -import org.bukkit.event.Cancellable -import org.bukkit.event.player.PlayerEvent - -class MultiblockDetectedEvent(): PlayerEvent, Cancellable { -} +//class MultiblockDetectedEvent(): PlayerEvent, Cancellable { +//} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt index dfc02b58f3..6a20dd6e0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt @@ -5,6 +5,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import org.bukkit.World object MultiblockEntities { private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) @@ -12,4 +15,42 @@ object MultiblockEntities { fun T.executeAsync(block: suspend () -> Unit) { multiblockCoroutineScope.launch { block.invoke() } } + + /** + * + **/ + fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { + val ionChunk = getIonChunk(world, x, y, z) ?: return null + + return ionChunk.multiblockManager[x, y, z] + } + + /** + * Add a new multiblock entity to the chunk + **/ + fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, entity: MultiblockEntity): Boolean { + val ionChunk = getIonChunk(world, x, y, z) ?: return false + + ionChunk.region.launch { + ionChunk.multiblockManager.addMultiblockEntity(entity, save = true) + } + + return true + } + + /** + * + **/ + fun removeMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { + val ionChunk = getIonChunk(world, x, y, z) ?: return null + + return ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) + } + + private fun getIonChunk(world: World, x: Int, y: Int, z: Int): IonChunk? { + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + return world.ion.getChunk(chunkX, chunkZ) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 9dff6af936..b73b9b1f3d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.newer +import com.google.common.collect.Multimap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -9,14 +10,22 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier3 +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf //TODO store the progress of migrated multiblocks here object MultiblockRegistration : IonServerComponent() { private val multiblocks: MutableMap = mutableMapOf() private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + /** + * The multiblocks grouped by their sign text. + * + * E.g. powerbank would contain all tiers of Power Banks + **/ + private val byDetectionName : Multimap = multimapOf() override fun onEnable() { initMultiblocks() + sortMultiblocks() log.info("Loaded ${multiblocks.size} multiblocks") } @@ -28,6 +37,12 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(NewPowerBankMultiblockTier3) } + private fun sortMultiblocks() { + for ((_, multi) in getAllMultiblocks()) { + byDetectionName[multi.name].add(multi) + } + } + private fun registerMultiblock(multiblock: Multiblock) { val name = multiblock.javaClass.simpleName ?: throw IllegalArgumentException("Provided anonymous multiblock class!") @@ -39,4 +54,12 @@ object MultiblockRegistration : IonServerComponent() { } fun getAllMultiblocks() = multiblocks + + fun getBySignName(name: String): List { + return byDetectionName[name].toList() + } + + fun getByStorageName(name: String): Multiblock? { + return multiblocks[name] + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 3a82d88342..9231e4a8f1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material @@ -12,7 +13,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataType -abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock { +abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock { abstract val tierMaterial: Material override val name = "newpowerbank" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 1b95fe1270..44ad89ab3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.power.MergeNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode @@ -17,6 +18,7 @@ enum class NodeType(val clazz: Class) { POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), POWER_FLOW_METER(PowerFlowMeter::class.java), + MERGE_NODE(MergeNode::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt index 628279ab73..c6ccebc8ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -14,11 +14,11 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class MergeNode(override val network: ChunkTransportNetwork) : SingleNode { +class MergeNode(override val network: ChunkPowerNetwork) : SingleNode { override val relationships: MutableSet = ObjectOpenHashSet() override var position: BlockKey by Delegates.notNull() - constructor(network: ChunkTransportNetwork, position: BlockKey) : this(network) { + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 70e6ee2dbc..9d203dae5d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -78,7 +78,7 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { val room = multi.maxPower - multi.getPower() val power = origin.finishExtraction(step, room) - println("Finished extraction, returned $power power") +// println("Finished extraction, returned $power power") multi.addPower(power) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 1b9d515485..64e4a04886 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -57,8 +57,8 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory addFlowMeter(key) // Merge node behavior - snapshot.type == Material.IRON_BLOCK -> addSourceNode(key) - snapshot.type == Material.REDSTONE_BLOCK -> addSourceNode(key) + snapshot.type == Material.IRON_BLOCK -> addMergeNode(key) + snapshot.type == Material.REDSTONE_BLOCK -> addMergeNode(key) // Split power evenly // block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) @@ -179,7 +179,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory Unit) = scope.launch { block.invoke(this) } + companion object { val scope = CoroutineScope(ForkJoinPool(64).asCoroutineDispatcher() + SupervisorJob()) const val MAX_SIZE: Int = 50 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 880d48dac5..c8a6fc3581 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -37,6 +37,8 @@ import net.horizonsend.ion.server.features.misc.ProxyMessaging import net.horizonsend.ion.server.features.misc.Shuttles import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.nations.NationsBalancing import net.horizonsend.ion.server.features.nations.NationsMap @@ -130,6 +132,8 @@ val components: List = listOf( Multiblocks, MultiblockRecipes, + MultiblockRegistration, + MultiblockAccess, PowerMachines, AreaShields, From 3e2eaa00004f4b3500c79495a1179f39492c1fd5 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 20 Jun 2024 00:33:49 -0500 Subject: [PATCH 066/500] reworking ticking a bit --- .../multiblock/ChunkMultiblockManager.kt | 43 +++++++++++-------- .../multiblock/entity/MultiblockEntity.kt | 17 ++++---- ...ity.kt => AsyncTickingMultiblockEntity.kt} | 15 ++++--- .../entity/type/PoweredMultiblockEntity.kt | 9 ++-- .../entity/type/ProcessingMultiblockEntity.kt | 4 +- .../type/SyncTickingMultiblockEntity.kt | 35 +++++++++++++++ .../multiblock/type/misc/TestMultiblock.kt | 10 ++--- .../ion/server/features/world/IonWorld.kt | 8 ++-- .../server/features/world/chunk/IonChunk.kt | 3 ++ 9 files changed, 98 insertions(+), 46 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/{TickingMultiblockEntity.kt => AsyncTickingMultiblockEntity.kt} (54%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 956cff3e96..2ba31d4bc1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -1,16 +1,17 @@ package net.horizonsend.ion.server.features.multiblock import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext @@ -26,7 +27,8 @@ class ChunkMultiblockManager(val chunk: IonChunk) { private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** All the ticked multiblock entities of this chunk */ - private val tickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + private val syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + private val asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** * Logic upon the chunk being ticked @@ -48,19 +50,20 @@ class ChunkMultiblockManager(val chunk: IonChunk) { fun getAllMultiblockEntities() = multiblockEntities - private fun tickAllMultiblocks() = tickingMultiblockEntities.forEachValue(tickingMultiblockEntities.size.toLong(), ::handleMultiblockTick) - - private fun handleMultiblockTick(multiblock: TickingMultiblockEntity): Boolean = try { - if (multiblock.tickAsync) { - Multiblocks.multiblockCoroutineScope.launch { multiblock.tick() } - } else runBlocking { multiblock.tick() } - - true - } catch (e: Throwable) { - log.warn("Exception ticking multiblock ${e.message}") - e.printStackTrace() + private fun tickAllMultiblocks() { + for ((key, syncTicking) in syncTickingMultiblockEntities) runCatching { + syncTicking.tick() + }.onFailure { e -> + log.warn("Exception ticking multiblock ${syncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") + e.printStackTrace() + } - false + for ((key, asyncTicking) in asyncTickingMultiblockEntities) runCatching { + Multiblocks.multiblockCoroutineScope.launch { asyncTicking.tickAsync() } + }.onFailure { e -> + log.warn("Exception ticking async multiblock ${asyncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") + e.printStackTrace() + } } /** @@ -100,8 +103,12 @@ class ChunkMultiblockManager(val chunk: IonChunk) { fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true) { multiblockEntities[entity.locationKey] = entity - if (entity is TickingMultiblockEntity) { - tickingMultiblockEntities[entity.locationKey] = entity + if (entity is SyncTickingMultiblockEntity) { + syncTickingMultiblockEntities[entity.locationKey] = entity + } + + if (entity is AsyncTickingMultiblockEntity) { + asyncTickingMultiblockEntities[entity.locationKey] = entity } if (save) saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) @@ -154,7 +161,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { val key = toBlockKey(x, y, z) val entity = multiblockEntities.remove(key) - tickingMultiblockEntities.remove(key) + syncTickingMultiblockEntities.remove(key) return entity } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 3040511312..a1cabce651 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block @@ -70,17 +70,18 @@ abstract class MultiblockEntity( /** * Gets the sign of this multiblock **/ - suspend fun getSign(): Sign? { + fun getSign(): Sign? { val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) - return getBukkitBlockState(world.getBlockAt(signLoc.x, signLoc.y, signLoc.z), loadChunks = false) as? Sign + return getBlockIfLoaded(world, signLoc.x, signLoc.y, signLoc.z)?.state as? Sign } - suspend fun isIntact(): Boolean { - val sign = getSign() ?: return false - - return multiblock.signMatchesStructureAsync(sign) - } + fun isIntact(): Boolean = multiblock.blockMatchesStructure( + world.getBlockAt(x, y, z), + signDirection.oppositeFace, + loadChunks = false, + particles = false + ) /** * diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/TickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/AsyncTickingMultiblockEntity.kt similarity index 54% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/TickingMultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/AsyncTickingMultiblockEntity.kt index 97f775e07b..1cf70c23d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/TickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/AsyncTickingMultiblockEntity.kt @@ -3,14 +3,19 @@ package net.horizonsend.ion.server.features.multiblock.entity.type /** * Any multiblock that should be ticked along with the world **/ -interface TickingMultiblockEntity { +interface AsyncTickingMultiblockEntity { /** - * Whether the tick should be run async + * The logic that is run upon world tick **/ - val tickAsync: Boolean + suspend fun tickAsync() /** - * The logic that is run upon world tick + * + **/ + fun shouldAsyncTick(): Boolean = true + + /** + * **/ - suspend fun tick() + fun shouldAsyncCheckIntegrity(): Boolean = true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 18948dec46..90e4d20570 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -84,10 +84,11 @@ interface PoweredMultiblockEntity { suspend fun updatePowerVisually() { //TODO replace this require(this is MultiblockEntity) - - val sign = getSign() ?: return - sign.front().line(2, formatPower()) - Tasks.sync { sign.update() } + Tasks.sync { + val sign = getSign() ?: return@sync + sign.front().line(2, formatPower()) + sign.update() + } } fun formatPower(): Component = ofChildren(prefixComponent, text(powerUnsafe, GREEN)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt index c1aefc0bfa..cc2d3abc9b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -23,7 +23,7 @@ abstract class ProcessingMultiblockEntity( signOffset: BlockFace, val requiredProgress: Int, var currentProgress: Int = 0 -) : MultiblockEntity(type, x, y, z, world, signOffset), TickingMultiblockEntity { +) : MultiblockEntity(type, x, y, z, world, signOffset), SyncTickingMultiblockEntity { //TODO // -recipe system @@ -32,7 +32,7 @@ abstract class ProcessingMultiblockEntity( abstract fun startProcessing() abstract fun process() - override suspend fun tick() { + override fun tick() { if (currentProgress >= requiredProgress) { currentProgress = 0 finishProcessing() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt new file mode 100644 index 0000000000..ca634e0fb2 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt @@ -0,0 +1,35 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity + +/** + * Any multiblock that should be ticked along with the world + **/ +interface SyncTickingMultiblockEntity { + /** + * The logic that is run upon world tick + **/ + fun tick() + + /** + * + **/ + fun shouldTick(): Boolean = true + + /** + * + **/ + fun shouldCheckIntegrity(): Boolean = true + + companion object { + /** + * Checks whether this entity is able / ready to tick. + **/ + fun preTick(multiblockEntity: T): Boolean { + if (multiblockEntity !is SyncTickingMultiblockEntity) return false + if (multiblockEntity.shouldCheckIntegrity() && !multiblockEntity.isIntact()) return false + + return multiblockEntity.shouldTick() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index cb9df18e7c..aac1a19191 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.TickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -57,14 +57,14 @@ object TestMultiblock : Multiblock(), EntityMultiblock Date: Fri, 21 Jun 2024 14:50:17 -0500 Subject: [PATCH 067/500] organization --- .../server/features/multiblock/Multiblock.kt | 1 + .../multiblock/MultiblockStructureFixer.kt | 1 + .../entity/type/PoweredMultiblockEntity.kt | 9 ++------- .../multiblock/newer/MultiblockEntities.kt | 10 ---------- .../multiblock/{ => shape}/BlockRequirement.kt | 6 +++--- .../multiblock/{ => shape}/MultiblockShape.kt | 17 +++++++---------- .../type/ammo/AmmoLoaderMultiblock.kt | 2 +- .../multiblock/type/ammo/AmmoPressMultiblock.kt | 2 +- .../type/ammo/MissileLoaderMultiblock.kt | 2 +- .../multiblock/type/areashield/AreaShield10.kt | 2 +- .../multiblock/type/areashield/AreaShield20.kt | 2 +- .../multiblock/type/areashield/AreaShield30.kt | 2 +- .../multiblock/type/areashield/AreaShield5.kt | 2 +- .../type/autocrafter/AutoCrafterMultiblock.kt | 2 +- .../type/charger/ChargerMultiblock.kt | 2 +- .../type/checklist/BargeReactorMultiBlock.kt | 2 +- .../checklist/BattleCruiserReactorMultiblock.kt | 2 +- .../type/checklist/CruiserReactorMultiblock.kt | 2 +- .../cosmeticmultiblocks/PyrotechnicMachine.kt | 2 +- .../type/defense/AntiAirCannonMultiblock.kt | 2 +- .../ConnectedDockingTubeMultiblock.kt | 2 +- .../DisconnectedDockingTubeMultiblock.kt | 2 +- .../type/dockingtube/DockingTubeMultiblock.kt | 2 +- .../multiblock/type/drills/DrillMultiblock.kt | 2 +- .../farming/harvester/HarvesterMultiblock.kt | 2 +- .../type/farming/planter/PlanterMultiblock.kt | 2 +- .../type/gas/GasCollectorMultiblock.kt | 2 +- .../type/gas/GasPowerPlantMultiblock.kt | 2 +- .../multiblock/type/gas/VentMultiblock.kt | 2 +- .../type/generator/GeneratorMultiblock.kt | 2 +- .../AmplifiedGravityWellMultiblock.kt | 2 +- .../StandardGravityWellMultiblock.kt | 2 +- .../type/hyperdrive/HyperdriveMultiblock.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass1.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass2.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass3.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass4.kt | 2 +- .../type/industry/CentrifugeMultiblock.kt | 2 +- .../type/industry/CircuitfabMultiblock.kt | 2 +- .../type/industry/CompressorMultiblock.kt | 2 +- .../type/industry/FabricatorMultiblock.kt | 2 +- .../type/industry/GasFurnaceMultiblock.kt | 2 +- .../type/industry/PlatePressMultiblock.kt | 2 +- .../mininglasers/MiningLaserMultiblockTier1.kt | 2 +- .../mininglasers/MiningLaserMultiblockTier2.kt | 2 +- .../mininglasers/MiningLaserMultiblockTier3.kt | 2 +- .../mininglasers/MiningLaserMultiblockTier4.kt | 2 +- .../multiblock/type/misc/AirlockMultiblock.kt | 3 +-- .../multiblock/type/misc/CryoPodMultiblock.kt | 2 +- .../type/misc/DecomposerMultiblock.kt | 2 +- .../multiblock/type/misc/DisposalMultiblock.kt | 2 +- .../multiblock/type/misc/FuelTankMultiblock.kt | 2 +- .../type/misc/ItemSplitterMultiblock.kt | 2 +- .../type/misc/LandingGearMultiblock.kt | 2 +- .../multiblock/type/misc/MagazineMultiblock.kt | 2 +- .../multiblock/type/misc/MobDefender.kt | 2 +- .../multiblock/type/misc/OdometerMultiblock.kt | 2 +- .../type/misc/ShipFactoryMultiblock.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 2 +- .../type/misc/TractorBeamMultiblock.kt | 2 +- .../NavigationComputerMultiblockAdvanced.kt | 2 +- .../NavigationComputerMultiblockBasic.kt | 2 +- .../type/particleshield/BoxShieldMultiblock.kt | 2 +- .../particleshield/EventShieldMultiblock.kt | 2 +- .../particleshield/ShieldMultiblockClass08.kt | 2 +- .../particleshield/ShieldMultiblockClass08i.kt | 2 +- .../particleshield/ShieldMultiblockClass20.kt | 2 +- .../particleshield/ShieldMultiblockClass30.kt | 2 +- .../particleshield/ShieldMultiblockClass65.kt | 2 +- .../particleshield/ShieldMultiblockClass85.kt | 2 +- .../type/powerbank/PowerBankMultiblock.kt | 2 +- .../type/powerbank/PowerCellMultiblock.kt | 2 +- .../powerbank/new/NewPowerBankMultiblock.kt | 2 +- .../type/powerfurnace/PowerFurnaceMultiblock.kt | 2 +- .../type/printer/ArmorPrinterMultiblock.kt | 2 +- .../type/printer/CarbonPrinterMultiblock.kt | 2 +- .../type/printer/CarbonProcessorMultiblock.kt | 2 +- .../type/printer/GlassPrinterMultiblock.kt | 2 +- .../type/printer/PrinterMultiblock.kt | 2 +- .../type/printer/TechnicalPrinterMultiblock.kt | 2 +- .../LaserCannonStarshipWeaponMultiblock.kt | 2 +- .../PlasmaCannonStarshipWeaponMultiblock.kt | 2 +- .../PulseCannonStarshipWeaponMultiblock.kt | 2 +- .../CapitalBeamStarshipWeaponMultiblock.kt | 2 +- .../event/CthulhuBeamMultiblock.kt | 2 +- .../FlamethrowerStarshipWeaponMultiblock.kt | 2 +- .../event/MiniPhaserStarshipWeaponMultiblock.kt | 2 +- .../PumpkinCannonStarshipWeaponMultiblock.kt | 2 +- .../event/SonicMissileWeaponMultiblock.kt | 2 +- .../AIHeavyLaserStarshipWeaponMultiblock.kt | 2 +- .../ArsenalRocketStarshipWeaponMultiblock.kt | 2 +- .../heavy/HeavyLaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/PhaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/RocketStarshipWeaponMultiblock.kt | 2 +- .../heavy/TorpedoStarshipWeaponMultiblock.kt | 2 +- .../PointDefenseStarshipWeaponMultiblock.kt | 2 +- .../turret/HeavyTurretMultiblock.kt | 2 +- .../turret/IonTurretMultiblock.kt | 2 +- .../turret/LightTurretMultiblock.kt | 2 +- .../turret/QuadTurretMultiblock.kt | 2 +- .../turret/TriTurretMultiblock.kt | 2 +- .../starship/subsystem/thruster/ThrusterType.kt | 2 +- 102 files changed, 110 insertions(+), 127 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{ => shape}/BlockRequirement.kt (74%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{ => shape}/MultiblockShape.kt (97%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 506c3e0fc1..2e2c608e8a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt index 7287adcf10..b1d671cb08 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.world.data.DataFixer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 90e4d20570..5de52e9b09 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -1,9 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.entity.type -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.launch import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -28,7 +24,7 @@ interface PoweredMultiblockEntity { powerUnsafe = correctedPower //TODO better solution - powerUpdateScope.launch { updatePowerVisually() } + updatePowerVisually() } fun getPower(): Int { @@ -73,7 +69,6 @@ interface PoweredMultiblockEntity { companion object { private val prefixComponent = text("E: ", NamedTextColor.YELLOW) - private val powerUpdateScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) } /** Store power data */ @@ -81,7 +76,7 @@ interface PoweredMultiblockEntity { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, powerUnsafe) } - suspend fun updatePowerVisually() { + fun updatePowerVisually() { //TODO replace this require(this is MultiblockEntity) Tasks.sync { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt index 6a20dd6e0c..3c7ce0944d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt @@ -1,21 +1,11 @@ package net.horizonsend.ion.server.features.multiblock.newer -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import org.bukkit.World object MultiblockEntities { - private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) - - fun T.executeAsync(block: suspend () -> Unit) { - multiblockCoroutineScope.launch { block.invoke() } - } - /** * **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt similarity index 74% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 2bee8808a4..6a2a60e931 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock +package net.horizonsend.ion.server.features.multiblock.shape import org.bukkit.block.Block import org.bukkit.block.BlockFace @@ -6,10 +6,10 @@ import org.bukkit.block.data.BlockData class BlockRequirement( var example: BlockData, - private val check: (Block, BlockFace, Boolean) -> Boolean, + private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean ) { - operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = check.invoke(block, inward, loadChunks) + operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) suspend fun checkAsync(block: Block, inward: BlockFace, loadChunks: Boolean) = asyncCheck.invoke(block, inward, loadChunks) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 4e8eb4aed4..03604e9bae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock +package net.horizonsend.ion.server.features.multiblock.shape import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks @@ -49,9 +49,6 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.Furnace import org.bukkit.block.data.type.Slab import java.util.EnumSet -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set class MultiblockShape { // Cache of direction to requirement, so it doesn't need to be calculated every time based on the direction @@ -268,7 +265,7 @@ class MultiblockShape { fun type(type: Material) { val requirement = BlockRequirement( example = type.createBlockData(), - check = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, + syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type } ) @@ -280,7 +277,7 @@ class MultiblockShape { val requirement = BlockRequirement( example = types.first().createBlockData(), - check = { block, _, loadChunks -> + syncCheck = { block, _, loadChunks -> typeSet.contains(if (loadChunks) block.type else block.getTypeSafe()) }, asyncCheck = { block, _, loadChunks -> @@ -298,7 +295,7 @@ class MultiblockShape { fun customBlock(customBlock: CustomBlock) { val requirement = BlockRequirement( example = customBlock.blockData, - check = { block, _, loadChunks -> + syncCheck = { block, _, loadChunks -> if (loadChunks) CustomBlocks.getByBlock(block) else { getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } } === customBlock @@ -347,7 +344,7 @@ class MultiblockShape { this as Slab this.type = Slab.Type.DOUBLE }, - check = { block, _, loadChunks -> + syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) blockData is Slab && blockData.type == Slab.Type.DOUBLE }, @@ -363,7 +360,7 @@ class MultiblockShape { fun terracottaOrDoubleslab() { BlockRequirement( example = Material.TERRACOTTA.createBlockData(), - check = { block, _, loadChunks -> + syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) val blockType = if (loadChunks) block.type else block.getTypeSafe() @@ -460,7 +457,7 @@ class MultiblockShape { fun machineFurnace() = complete(BlockRequirement( example = Material.FURNACE.createBlockData(), - check = check@{ block, inward, loadChunks -> + syncCheck = check@{ block, inward, loadChunks -> val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockSateSafe(block.world, block.x, block.y, block.z) ?: return@check false if (blockData.bukkitMaterial != Material.FURNACE) return@check false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 83dc3b0018..b5479f7954 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index ac20f46f18..92d45ac892 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.custom.items.attribute.AmmunitionRefi import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index 6eb6ed7b27..0c8d4b66cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt index d8de21d911..ce2c7b6e7d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object AreaShield10 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 10) { override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt index 4be75a93ac..62c1ac963d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object AreaShield20 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 20) { override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt index a69d8bb9a6..fb2722d899 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object AreaShield30 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 30) { override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt index c205107121..324ac065f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object AreaShield5 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 5) { override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index e8ef1dd069..6831eadb3f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -5,7 +5,7 @@ import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt index b7f0c4a0ab..8970d670d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.custom.items.component.CustomComponen import net.horizonsend.ion.server.features.custom.items.component.PowerStorage import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt index 9f77a9bf92..5c878c65cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material import org.bukkit.block.Sign import org.bukkit.block.sign.Side diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt index 264e3bdcee..a643dc8bc0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material import org.bukkit.block.Sign import org.bukkit.block.sign.Side diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt index 451fe521ec..6ba6f4c62a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material import org.bukkit.block.Sign import org.bukkit.block.sign.Side diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt index c40e0cfaef..862c9f59ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.cosmeticmultiblocks import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt index c1ebfbac61..172fe4d83c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.machine.AntiAirCannons import net.horizonsend.ion.server.features.machine.AntiAirCannons.isOccupied import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.projectile.AntiAirCannonProjectile diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt index 706b4df975..e3242c0981 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/ConnectedDockingTubeMultiblock.kt @@ -4,7 +4,7 @@ import com.manya.pdc.DataTypes import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.successActionMessage import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt index f042afb0bd..3bc2d6bdb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DisconnectedDockingTubeMultiblock.kt @@ -4,7 +4,7 @@ import com.manya.pdc.DataTypes import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.successActionMessage import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt index f255f44d25..2aa3c0c510 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/dockingtube/DockingTubeMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.dockingtube import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index eb08524130..f8ca106ebc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.userErrorSubtitle import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 84f35d4b57..00d99ded10 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.harvester import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.multiblock.type.farming.CropMultiblock import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index c54c4b99c2..20f007425f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.planter import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.multiblock.type.farming.CropMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt index 3f876b09ac..959fa3212c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.gas.collection.CollectedGas import net.horizonsend.ion.server.features.gas.type.Gas import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt index 11b8943e89..c043fea938 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt index 80b2924745..738e8dad61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.custo import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt index 6f3d17216d..3ff609bfe0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.generator import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Effect diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt index f04bcc444f..690d28e608 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.gravitywell -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material object AmplifiedGravityWellMultiblock : GravityWellMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt index 6d47b3a37f..402fc2714b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.gravitywell -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object StandardGravityWellMultiblock : GravityWellMultiblock() { override val name = "gravitywell" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt index 18a08faaef..62a0d0d705 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive import net.horizonsend.ion.server.features.gui.custom.navigation.NavigationSystemMapGui import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt index f23bf7c0fd..0d434df469 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass1 : HyperdriveMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt index fa792de45d..660d07edab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass2 : HyperdriveMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt index 1d24aa53a6..a8c72ed2f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass3 : HyperdriveMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt index 555417574e..bec62b6d68 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.hyperdrive -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i object HyperdriveMultiblockClass4 : HyperdriveMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index 2521c32138..973de293e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt index 7c791c2985..6eaafd3c04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt index 7c930d1065..9dad988842 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt index d16a39cd5b..ead91eef02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt index bbd83413dd..3118c07898 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt index efe52f38db..a015fae7d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt index 719e7b9d71..98f2a720a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.mininglasers -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt index 13e8656b45..20cf5bbdd4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.mininglasers -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt index 68ce7439c3..7dc0b0e7f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.mininglasers -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt index 7b7ab691b2..afc749888c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.mininglasers -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt index 7c5d6276d6..22c6a36872 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.getFacing @@ -14,7 +14,6 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.MultipleFacing import org.bukkit.block.data.Orientable -import org.bukkit.block.sign.Side import org.bukkit.block.sign.Side.FRONT import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt index b580a8ddb1..ff75511dc3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt index ad0450f606..4646119efd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.BlockFace import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt index 6974c17c0f..59c0a02045 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/FuelTankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/FuelTankMultiblock.kt index b6b00c7b12..15c372e479 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/FuelTankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/FuelTankMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material object FuelTankMultiblock : Multiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt index e56f15401b..74360b8c50 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SPLITTER_DIRECTION diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt index 90efa77991..2609b7f032 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.LandingGearSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt index ff1bc2e10d..e763219ab4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material abstract class AbstractMagazineMultiblock : Multiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index f0e73e503b..638c6040f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.Bukkit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt index b49faa5075..6cb8fb970d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt index 58fef6b569..ce0c073261 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.features.starship.factory.StarshipFactories diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index aac1a19191..e81d9d9975 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -5,10 +5,10 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TractorBeamMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TractorBeamMultiblock.kt index c56a6bd205..cd7c02b5b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TractorBeamMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TractorBeamMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.listener.SLEventListener diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt index a7a772e005..47c5d41a80 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.navigationcomputer -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape sealed class NavigationComputerMultiblockAdvanced : NavigationComputerMultiblock() { override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt index 54907b4d6b..2a58bb50d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.navigationcomputer -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object NavigationComputerMultiblockBasic : NavigationComputerMultiblock() { override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/BoxShieldMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/BoxShieldMultiblock.kt index 5c2e582ff0..e253257a28 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/BoxShieldMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/BoxShieldMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.msg diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt index 4e9bcddd8d..ca699c72ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08.kt index 26eaed124b..6cfbe34ff9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape sealed class ShieldMultiblockClass08(private val sideX: Int) : SphereShieldMultiblock() { override val maxRange = 10 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08i.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08i.kt index 66ca355da2..7fda3aa243 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08i.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass08i.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object ShieldMultiblockClass08i : SphereShieldMultiblock() { override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass20.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass20.kt index ba4185dcb5..1f4ad398d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass20.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass20.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.kyori.adventure.text.Component object ShieldMultiblockClass20 : SphereShieldMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt index 4d57a0f50d..472624623e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object ShieldMultiblockClass30 : SphereShieldMultiblock() { override val maxRange = 22 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt index 8441451862..d1c3890b54 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object ShieldMultiblockClass65 : SphereShieldMultiblock() { override val maxRange = 30 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt index 3ccad6edda..f5756b220b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape object ShieldMultiblockClass85 : SphereShieldMultiblock() { override val maxRange = 35 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt index 547712d37e..fd4e5d747d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt index f275b25b07..1c60e9c378 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock object PowerCellMultiblock : Multiblock(), PowerStoringMultiblock { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 9231e4a8f1..0b438a6a69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt index 47710282f5..e016a1ea69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.powerfurnace import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt index b3d7adc5d9..a948e80849 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.printer -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.isStainedTerracotta import org.bukkit.Material import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt index f0066c0f1b..fc34401672 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.printer -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.isConcretePowder import org.bukkit.Material import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt index 9343b04a06..d25503b7bc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.printer import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/GlassPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/GlassPrinterMultiblock.kt index 560eb1ffe8..1e1e5fed96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/GlassPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/GlassPrinterMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.printer -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt index 4899a02c89..eb0e8cec1a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.printer import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt index fe1ee91bfa..b9b0c5be14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.printer -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt index ebd0ac2fae..c986a69be2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LaserCannonWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt index 041fff1bd4..30bd1ef4b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PlasmaCannonWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt index 5a8bb3d783..9599062b9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PulseCannonWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt index 260a8b58d7..061ec5261c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.CapitalBeamWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt index 064753381b..8c7ca5c5d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.CthulhuBeamSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt index 8aa656fb3b..87d6b471ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.FlamethrowerWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt index 71cff08dfa..28eed2ab5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.MiniPhaserWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt index 5d124ef302..bc46bb303e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.PumpkinCannonWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt index 2be9785e6e..a47d085fa7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.SonicMissileWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt index 19638bae72..31c067dd5e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.AIHeavyLaserWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt index f40e843ad1..0fc98981e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.ArsenalRocketStarshipWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt index 0ccef35a0f..25fff73420 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.HeavyLaserWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt index 04b7163dbc..4e77b715a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.PhaserWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt index b10837ce4b..5d301e8493 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.RocketWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt index 45a51f7fde..58e0a9d7f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TorpedoWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt index 12bf97b4f7..9acb11fa1d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PointDefenseSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt index 4b512ccddf..3d2ff94c24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.HeavyTurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt index 21dd15f615..a11ca0fa17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt index 57a2f8219b..3b22bb7593 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LightTurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt index dc120e31f7..3baa98215f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt index 5ba3778ae0..8b8515c786 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TriTurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterType.kt index ae8478f7e0..6b77fb0a51 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/thruster/ThrusterType.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.starship.subsystem.thruster -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.miscellaneous.utils.isGlass import net.horizonsend.ion.server.miscellaneous.utils.isGlassPane From 13ffbf26e6e5c7d39ad4a63b1148f0230216eb8f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 21 Jun 2024 15:15:15 -0500 Subject: [PATCH 068/500] cache reflection --- .../multiblock/util/AsyncBlockUtils.kt | 50 +++++++++---------- .../ion/server/miscellaneous/utils/Blocks.kt | 12 +++++ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt index abccbd85ef..c6ae2db891 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt @@ -2,14 +2,15 @@ package net.horizonsend.ion.server.features.multiblock.util import net.minecraft.world.level.block.state.BlockState as NMSBlockState import org.bukkit.block.BlockState as BukkitBlockState -import kotlinx.coroutines.CompletableDeferred +import com.google.common.cache.CacheBuilder +import com.google.common.cache.CacheLoader +import com.google.common.cache.LoadingCache import kotlinx.coroutines.Deferred import kotlinx.coroutines.future.asDeferred import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.loadChunkAsync import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded @@ -74,7 +75,7 @@ suspend fun getBlockSnapshotAsync(world: World, key: Long, loadChunks: Boolean = suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } -suspend fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { +fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { val serverLevel: ServerLevel = block.world.minecraft val blockPos = (block as CraftBlock).position @@ -89,23 +90,16 @@ suspend fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { return serverLevel.getChunk(chunkX, chunkZ).getBlockEntity(blockPos, LevelChunk.EntityCreationType.IMMEDIATE) } - if (!loadChunks) { - return null - } - - val entity = CompletableDeferred() - - loadChunkAsync(block.world, chunkX, chunkZ) { - entity.complete(it.minecraft.getBlockEntity(blockPos)) - } + if (!loadChunks) return null - return entity.await() + val chunk = block.world.getChunkAt(chunkX, chunkZ).minecraft + return chunk.getBlockEntity(blockPos) } @Suppress("UNCHECKED_CAST") -suspend fun getAndCastNMSTileEntity(block: Block, loadChunks: Boolean): T? = getNMSTileEntity(block, loadChunks) as? T +fun getAndCastNMSTileEntity(block: Block, loadChunks: Boolean): T? = getNMSTileEntity(block, loadChunks) as? T -suspend fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlockState? { +fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlockState? { // If this is the main thread, we don't need to do laggy reflection if (Bukkit.isPrimaryThread()) { return block.state @@ -113,7 +107,7 @@ suspend fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlock val world = block.world val blockPos = (block as CraftBlock).position - val data = getBlockSnapshotAsync(world, blockPos.x, blockPos.y, blockPos.z, loadChunks)?.data ?: return null + val data = getBlockDataSafe(world, blockPos.x, blockPos.y, blockPos.z, loadChunks) ?: return null val tileEntity = getNMSTileEntity(block, loadChunks) @@ -127,18 +121,24 @@ val getFactoryForMaterial: Method = CraftBlockStates::class.java.getDeclaredMeth isAccessible = true } +private val blockStateFactory: LoadingCache> = CacheBuilder.newBuilder() + .weakValues() + .build(CacheLoader.from { material -> + val factory = getFactoryForMaterial.invoke(null, material) + + factory to factory::class.java.getDeclaredMethod( + "createBlockState", + World::class.javaObjectType, + BlockPos::class.javaObjectType, + NMSBlockState::class.javaObjectType, + BlockEntity::class.javaObjectType + ) + }) + fun createBlockState(world: World, blockPos: BlockPos, data: BlockData, tileEntity: BlockEntity?): CraftBlockState { val material = CraftMagicNumbers.getMaterial((data as CraftBlockData).state.block) - val factory = getFactoryForMaterial.invoke(null, material) - - val blockStateFactory = factory::class.java.getDeclaredMethod( - "createBlockState", - World::class.javaObjectType, - BlockPos::class.javaObjectType, - NMSBlockState::class.javaObjectType, - BlockEntity::class.javaObjectType - ) + val (factory, blockStateFactory) = blockStateFactory[material] blockStateFactory.isAccessible = true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index b0a8174e3f..7deaf69b5a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -28,6 +28,18 @@ fun getBlockDataSafe(world: World, x: Int, y: Int, z: Int): BlockData? { return getNMSBlockSateSafe(world, x, y, z)?.createCraftBlockData() } +/** + * Get block data, with an option to handle chunk loading to get the data + */ +fun getBlockDataSafe(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): BlockData? { + val data = getBlockDataSafe(world, x, y, z) + + if (data != null) return data + if (!loadChunks) return null + + return world.getBlockData(x, y, z) +} + /** * Gets the block state at the given location if loaded. Sync only. */ From b1696a28cc7fa505cad729125cb623aa5acc299b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 21 Jun 2024 23:54:06 -0500 Subject: [PATCH 069/500] handle some race conditions, fix solars --- .../multiblock/ChunkMultiblockManager.kt | 3 ++ .../server/features/multiblock/Multiblocks.kt | 9 ++--- .../multiblock/entity/MultiblockEntity.kt | 3 ++ .../entity/type/PoweredMultiblockEntity.kt | 2 +- .../multiblock/newer/MultiblockAccess.kt | 15 +++++++-- .../multiblock/type/InteractableMultiblock.kt | 3 +- .../powerbank/new/NewPowerBankMultiblock.kt | 21 ++++++++++-- .../transport/network/ChunkPowerNetwork.kt | 22 ++----------- .../node/power/PowerExtractorNode.kt | 2 +- .../transport/node/power/PowerInputNode.kt | 33 +++++++++---------- .../features/transport/step/PowerStep.kt | 6 ++-- .../server/features/transport/step/Step.kt | 4 +-- 12 files changed, 67 insertions(+), 56 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 2ba31d4bc1..cdd0347c80 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -161,7 +161,10 @@ class ChunkMultiblockManager(val chunk: IonChunk) { val key = toBlockKey(x, y, z) val entity = multiblockEntities.remove(key) + entity?.removed = true + syncTickingMultiblockEntities.remove(key) + asyncTickingMultiblockEntities.remove(key) return entity } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 635ac09e5e..90ec2101c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -93,9 +93,6 @@ import net.horizonsend.ion.server.features.multiblock.type.particleshield.Shield import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass30 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass65 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass85 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerCellMultiblock import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 @@ -187,9 +184,9 @@ object Multiblocks : IonServerComponent() { registerMultiblock(PowerFurnaceMultiblockTier2) registerMultiblock(PowerFurnaceMultiblockTier3) - registerMultiblock(PowerBankMultiblockTier1) - registerMultiblock(PowerBankMultiblockTier2) - registerMultiblock(PowerBankMultiblockTier3) +// registerMultiblock(PowerBankMultiblockTier1) +// registerMultiblock(PowerBankMultiblockTier2) +// registerMultiblock(PowerBankMultiblockTier3) registerMultiblock(PowerCellMultiblock) registerMultiblock(ChargerMultiblockTier1) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index a1cabce651..d54e7f3db4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -33,6 +33,9 @@ abstract class MultiblockEntity( var world: World, var signDirection: BlockFace ): PDCSerializable { + /** Mark this entity as having been removed */ + var removed: Boolean = false + override val persistentDataType: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion val position: BlockKey get() = toBlockKey(x, y, z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 5de52e9b09..85cb6cce0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -80,7 +80,7 @@ interface PoweredMultiblockEntity { //TODO replace this require(this is MultiblockEntity) Tasks.sync { - val sign = getSign() ?: return@sync + val sign = getSign() ?: return@sync println("Tried to update visual on a multiblock without an intact sign") sign.front().line(2, formatPower()) sign.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index c9386a4d16..6ede0ce0d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -123,6 +123,17 @@ object MultiblockAccess : IonServerComponent() { return computeMultiblockAtLocation(world, x, y, z, face, true) } + fun getMultiblock(sign: Sign, checkStructure: Boolean, loadChunks: Boolean): Multiblock? { + if (!checkStructure) { + return sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING)?.let { + MultiblockRegistration.getByStorageName(it) + } + } + + val origin = sign.getMultiblockOrigin() + return getMultiblock(sign.world, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace, checkStructure, loadChunks) + } + /** * Handle the setup and creation of the multiblock. Assumes structure has already been checked. * @@ -143,8 +154,6 @@ object MultiblockAccess : IonServerComponent() { sign.isWaxed = true - println("Setting up") - multiblock.setupSign(detector, sign) sign.update(false, false) @@ -202,6 +211,8 @@ object MultiblockAccess : IonServerComponent() { // Possible multiblocks from the sign val possible = MultiblockRegistration.getBySignName(name) + if (possible.isEmpty()) return null + val found = computeMultiblockAtLocation( world, x, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt index a86b323fda..9181e215dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type import kotlinx.coroutines.launch import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.listener.SLEventListener import org.bukkit.block.Sign @@ -32,7 +33,7 @@ interface InteractableMultiblock { sign.z, checkStructure = true, loadChunks = false - ) + ) ?: MultiblockAccess.getMultiblock(sign, checkStructure = true, loadChunks = false) if (multiblock !is InteractableMultiblock) return@launch diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 0b438a6a69..0fd7e3789d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -1,19 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataType -abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock { +abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock, InteractableMultiblock { abstract val tierMaterial: Material override val name = "newpowerbank" @@ -76,6 +81,18 @@ abstract class NewPowerBankMultiblock } } + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val world = sign.world + val origin = getOrigin(sign) + + val entity = getMultiblockEntity(world, origin.x, origin.y, origin.z) as PowerBankEntity + + player.information("Entity: $entity") + player.information("Removed: ${entity.removed}") + player.information("Power: ${entity.getPower()}") + player.information("Unsafe Power: ${entity.powerUnsafe}") + } + abstract class PowerBankEntity( multiblock: NewPowerBankMultiblock<*>, x: Int, @@ -92,7 +109,7 @@ abstract class NewPowerBankMultiblock } override fun toString(): String { - return "POWER BANK TIER: $multiblock! Power: $powerUnsafe!!!" + return "POWER BANK TIER: $multiblock! ${world.name} $x $y $z Power: ${getPower()}!!!" } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index 7cc591b64d..483141d545 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -4,42 +4,32 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.coroutines.launch import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.filterValuesIsInstance import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace -import java.util.concurrent.ConcurrentHashMap class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { override val type: NetworkType = NetworkType.POWER override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) - /** - * A list of all the powered multiblock entities within the chunk - **/ - val poweredMultiblockEntities = ConcurrentHashMap() - /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() override val dataVersion: Int = 0 //TODO 1 override fun setup() { - collectPowerMultiblockEntities() + } override fun processBlockRemoval(key: Long) { manager.scope.launch { @@ -55,7 +45,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( }} private suspend fun tickSolars() { - for (solarPanel in nodes.filterValuesIsInstance().values.distinct()) { + for (solarPanel in solarPanels) { runCatching { solarPanel.startStep()?.invoke() }.onFailure { IonServer.slF4JLogger.error("Exception ticking solar panel! $it") it.printStackTrace() @@ -94,14 +84,6 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - private fun collectPowerMultiblockEntities() { - manager.chunk.multiblockManager.getAllMultiblockEntities().forEach { (key, entity) -> - if (entity !is PoweredMultiblockEntity) return@forEach - - poweredMultiblockEntities[key] = entity - } - } - companion object { const val POWER_EXTRACTOR_STEP = 1000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index c6be5faa15..b6a73f089b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -87,7 +87,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, val limit = getTransferPower() - val extractablePowerPool = extractableNodes.flatMap { it.multis } + val extractablePowerPool = extractableNodes.flatMap { it.getPoweredMultiblocks() } val sum = extractablePowerPool.sumOf { it.getPower() } if (sum == 0) return null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 9d203dae5d..ad8f8448ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship @@ -26,11 +27,6 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { override var position by Delegates.notNull() - /** - * Multiblocks that share this power input - **/ - val multis: MutableSet = ObjectOpenHashSet() - override val relationships: MutableSet = ObjectOpenHashSet() override fun isTransferableTo(node: TransportNode): Boolean { return node is PowerExtractorNode @@ -46,12 +42,9 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { override suspend fun buildRelations(position: BlockKey) { super.buildRelations(position) - - multis.clear() - multis.addAll(getPoweredMultiblocks(network)) } - private fun getPoweredMultiblocks(network: ChunkPowerNetwork): Iterable { + fun getPoweredMultiblocks(): Iterable { val x = getX(position) val y = getY(position) val z = getZ(position) @@ -62,7 +55,7 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { val newZ = z + offset.z val newKey = toBlockKey(newX, newY, newZ) - network.poweredMultiblockEntities[newKey] + network.manager.chunk.multiblockManager[newKey] as? PoweredMultiblockEntity } } @@ -73,28 +66,32 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { step as PowerTransportStep val origin = step.origin - val multi = multis.randomOrNull() ?: return + val multis = getPoweredMultiblocks() +// println("Multis before: $multis") + val destinationMultiblock = multis + .filter { it as MultiblockEntity; !it.removed } + .randomOrNull() ?: return // println("No multis! origin: $origin") - val room = multi.maxPower - multi.getPower() + val room = destinationMultiblock.maxPower - destinationMultiblock.getPower() val power = origin.finishExtraction(step, room) // println("Finished extraction, returned $power power") - multi.addPower(power) + destinationMultiblock.addPower(power) // println("Traversed nodes: ${step.traversedNodes}") step.traversedNodes.forEach { it.onCompleteChain(step, this, power) } -// if (step.origin.currentNode is SolarPanelNode) return -// + if (step.origin.currentNode is SolarPanelNode) return + // println(""" // Reached multiblock input // Origin: $origin // -// Selected $multi -// Added $power to $multi +// Selected $destinationMultiblock +// Added $power to $destinationMultiblock // """.trimIndent()) } @@ -113,5 +110,5 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { ) } - override fun toString(): String = "POWER INPUT NODE: ${multis.size} powered multiblocks, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" + override fun toString(): String = "POWER INPUT NODE: ${getPoweredMultiblocks().toList().size} powered multiblocks, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt index 29b30924a7..173b1a02c6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt @@ -13,7 +13,7 @@ data class PowerExtractorOriginStep( val extractable: List, override val traversedNodes: MutableSet = mutableSetOf(), ) : OriginStep { - override fun finishExtraction(final: TransportStep, amount: Int): Int { + override fun finishExtraction(final: TransportStep, remainingSpace: Int): Int { if (extractable.isEmpty()) return 0 // Store multis that still have power @@ -24,7 +24,7 @@ data class PowerExtractorOriginStep( // The maximum that should be extracted // If limited, pick the lower - val maxPower = min(amount, share) + val maxPower = min(remainingSpace, share) // Remaining power to take var remaining = maxPower @@ -68,7 +68,7 @@ data class SolarPowerOriginStep( override val traversedNodes: MutableSet = mutableSetOf(), ) : OriginStep { // Solar panels do not have any additional logic needed upon extraction - override fun finishExtraction(final: TransportStep, amount: Int): Int = amount + override fun finishExtraction(final: TransportStep, remainingSpace: Int): Int = power } data class PowerTransportStep( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index 70906f022f..df246c8123 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -36,9 +36,9 @@ interface OriginStep : Step { * Removes the appropriate amount of power. Returns the amount that was removed (and is available) * * @param final The final step of the chain - * @param amount The limit of extraction (will use either this value or the maximum amount defined in this config, whichever is lower) + * @param remainingSpace The limit of extraction (will use either this value or the maximum amount defined in this config, whichever is lower) **/ - fun finishExtraction(final: TransportStep, amount: Int): Int + fun finishExtraction(final: TransportStep, remainingSpace: Int): Int } interface TransportStep : Step { From 40238b919348068d33daae430a7bd5659f18e5ca Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 23 Jun 2024 22:34:40 -0500 Subject: [PATCH 070/500] redo stepping --- .../entity/type/PoweredMultiblockEntity.kt | 3 + .../configuration/TransportConfiguration.kt | 11 ++++ .../node/power/PowerExtractorNode.kt | 5 +- .../transport/node/type/DestinationNode.kt | 8 +++ .../transport/node/type/IntermediateNode.kt | 15 +++++ .../transport/step/head/HeadHolder.kt | 7 +++ .../features/transport/step/head/MultiHead.kt | 21 +++++++ .../transport/step/head/SingleHead.kt | 8 +++ .../features/transport/step/head/StepHead.kt | 23 ++++++++ .../step/head/power/MultiPowerHead.kt | 18 ++++++ .../step/head/power/PowerStepHead.kt | 5 ++ .../step/head/power/SinglePowerHead.kt | 55 ++++++++++++++++++ .../features/transport/step/new/NewStep.kt | 18 ++++++ .../step/origin/ExtractorPowerOrigin.kt | 58 +++++++++++++++++++ .../transport/step/origin/SolarPowerOrigin.kt | 6 ++ .../transport/step/origin/StepOrigin.kt | 6 ++ .../transport/step/result/ChangeStep.kt | 11 ++++ .../transport/step/result/MoveForward.kt | 10 ++++ .../transport/step/result/StepResult.kt | 9 +++ 19 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 85cb6cce0e..ef0afc2395 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -27,6 +27,9 @@ interface PoweredMultiblockEntity { updatePowerVisually() } + fun isEmpty() = getPower() <= 0 + fun isFull() = getPower() >= maxPower + fun getPower(): Int { return powerUnsafe } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt new file mode 100644 index 0000000000..2bfa7e6e18 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.transport.configuration + +import kotlinx.serialization.Serializable + +@Serializable +data class TransportConfiguration( + val extractorTickIntervalMS: Long, + val maxPowerRemovedPerExtractorTick: Int +) { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index b6a73f089b..37f18d2076 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode @@ -98,7 +99,9 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, } fun getTransferPower(): Int { - return (ChunkPowerNetwork.POWER_EXTRACTOR_STEP * ((System.currentTimeMillis() - lastTicked) / 2000.0)).roundToInt() + val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() + + return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() } override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt new file mode 100644 index 0000000000..6db77be95a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.transport.node.type + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.StepHead + +interface DestinationNode { + suspend fun finishChain(head: StepHead) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt new file mode 100644 index 0000000000..39fdd91009 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.transport.node.type + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.StepHead +import net.horizonsend.ion.server.features.transport.step.result.StepResult + +interface IntermediateNode { + /** + * Handle the stepping of power through this node + * + * This may create a new step for a single node, spawn off multiple steps, or more + * Each node defines how it is stepped. + **/ + suspend fun handleHeadStep(head: StepHead): StepResult +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt new file mode 100644 index 0000000000..ed1aebb675 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.step.head + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork + +interface HeadHolder { + var head: StepHead +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt new file mode 100644 index 0000000000..5ef91c09e0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt @@ -0,0 +1,21 @@ +package net.horizonsend.ion.server.features.transport.step.head + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork + +/** A head which branches into multiple sub-heads */ +interface MultiHead : StepHead { + val heads: MutableSet> + + /** Holder that allows the head within to be replaced */ + class MultiHeadHolder(override var head: StepHead) : HeadHolder + + // Just pass it forward + override suspend fun stepForward() { + heads.forEach { it.head.stepForward() } + } + + // Just pass it forward + override fun isDead(): Boolean { + return heads.all { it.head.isDead() } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt new file mode 100644 index 0000000000..8efbb0fd4b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.transport.step.head + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode + +interface SingleHead : StepHead { + var head: TransportNode +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt new file mode 100644 index 0000000000..a2bcf3dd0f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt @@ -0,0 +1,23 @@ +package net.horizonsend.ion.server.features.transport.step.head + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.step.new.NewStep + +interface StepHead { + val holder: HeadHolder + val parent: NewStep + var currentNode: TransportNode + + /** Nodes that this head has covered */ + val coveredNodes: MutableSet + + /** + * Moves this step forward + * If the head is to be replaced with a new one, return that. + **/ + suspend fun stepForward() + + /** Returns whether this head is dead */ + fun isDead(): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt new file mode 100644 index 0000000000..5d4af4c221 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.transport.step.head.power + +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.step.head.MultiHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep + +/** + * + * + **/ +class MultiPowerHead( + override val share: Double, + override val parent: NewStep, + override val coveredNodes: MutableSet = mutableSetOf(), + override val heads: MutableSet> = mutableSetOf() +) : MultiHead, PowerStepHead + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt new file mode 100644 index 0000000000..b50553b226 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.step.head.power + +interface PowerStepHead { + val share: Double +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt new file mode 100644 index 0000000000..dac2b5c462 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt @@ -0,0 +1,55 @@ +package net.horizonsend.ion.server.features.transport.step.head.power + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork as ChunkTransportNetwork1 +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.DestinationNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.SingleHead +import net.horizonsend.ion.server.features.transport.step.head.StepHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep + +/** + * Transferred power down a single path. + * + * + **/ +class SinglePowerHead( + override val holder: HeadHolder, + override var head: TransportNode, + override val parent: NewStep, + override val share: Double, + override val coveredNodes: MutableSet = mutableSetOf(), + override var currentNode: TransportNode +) : SingleHead, PowerStepHead { + private var isDead = false + + private fun setDead() { + isDead = true + } + + override fun isDead(): Boolean = isDead + + override suspend fun stepForward() { + val node = currentNode + + if (tryCast>(node) { finishChain(this@SinglePowerHead) }) return + + node as IntermediateNode + + val result = node.handleHeadStep(this as StepHead) + result.apply(holder as HeadHolder) + } + + // Get around runtime type erasure + private inline fun tryCast(instance: Any?, block: T.() -> Unit): Boolean { + if (instance is T) { + block(instance) + return true + } + + return false + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt new file mode 100644 index 0000000000..fa0dcf3c0e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.transport.step.new + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.StepHead +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin + +class NewStep( + val network: T, + val origin: StepOrigin, + override var head: StepHead, +) : HeadHolder { + suspend operator fun invoke() { + while (!head.isDead()) { + head.stepForward() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt new file mode 100644 index 0000000000..377eab62e5 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt @@ -0,0 +1,58 @@ +package net.horizonsend.ion.server.features.transport.step.origin + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode + +class ExtractorPowerOrigin( + val origin: PowerExtractorNode +) : StepOrigin { + /** + * Remove power from the origin extractor's multiblocks. + * + * @return the amount of power that could not be removed + **/ + fun removeOrigin(amount: Int): Int { + // List of multiblock entities that power may be taken from + val availableEntities = origin.extractableNodes + .flatMap { it.getPoweredMultiblocks() } + .distinct() + .filterNotTo(mutableListOf()) { (it as MultiblockEntity).removed || it.isEmpty() } + + val transportLimit = origin.getTransferPower() + + var removeRemaining = amount + + while (removeRemaining >= 0) { + val minRemove = availableEntities.minOfOrNull { it.getPower() } ?: break + + // Remove the minimum in any of the multis, the limit of what can be removed, or the remaining power to remove. + // Whichever is lowest. + val toRemove = minOf(minRemove, transportLimit, removeRemaining) + + val share = toRemove / availableEntities.size + val remainder = toRemove - (share * availableEntities.size) + + // Remove an equal share from each of the inventories + for (entity in availableEntities) { + entity as MultiblockEntity + if (entity.removed) continue + + // Should never be more than 0, but handle the possibility + val notRemoved = entity.removePower(share) + removeRemaining -= (notRemoved - share) + } + + // Remove the remainder, if able + // If not able, it can just be stuck onto the amount that couldn't be removed + availableEntities.firstOrNull { it.canRemovePower(remainder) }?.run { + removePower(remainder) + removeRemaining -= remainder + } + + availableEntities.removeAll { it.isEmpty() } + } + + return removeRemaining + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt new file mode 100644 index 0000000000..0affc4eec3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.step.origin + +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode + +class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt new file mode 100644 index 0000000000..9b7038c7b9 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.step.origin + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork + +interface StepOrigin { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt new file mode 100644 index 0000000000..bbffb5dab1 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.transport.step.result + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.StepHead + +class ChangeHead(val new: StepHead) : StepResult { + override fun apply(head: HeadHolder) { + head.head = new + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt new file mode 100644 index 0000000000..70aafa13a6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.step.result + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder + +class MoveForward : StepResult { + override fun apply(head: HeadHolder) { + val currentNode = head.head.currentNode + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt new file mode 100644 index 0000000000..11faa90ec3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.features.transport.step.result + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder + +interface StepResult { + fun apply(head: HeadHolder) +} + From e24b7af23549dd137c200493d810ff6ccfeb4469 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 24 Jun 2024 01:27:35 -0500 Subject: [PATCH 071/500] finish new step system (broken) --- .../configuration/TransportConfiguration.kt | 4 +- .../features/transport/node/TransportNode.kt | 12 +--- .../transport/node/power/EndRodNode.kt | 32 ++++----- .../transport/node/power/MergeNode.kt | 32 ++++----- .../node/power/PowerExtractorNode.kt | 52 +++++++------- .../transport/node/power/PowerFlowMeter.kt | 36 ++++------ .../transport/node/power/PowerInputNode.kt | 71 +++++++++---------- .../transport/node/power/SolarPanelNode.kt | 65 +++++++++-------- .../transport/node/power/SpongeNode.kt | 32 ++++----- .../transport/node/type/DestinationNode.kt | 4 +- .../transport/node/type/IntermediateNode.kt | 7 +- .../transport/node/type/SourceNode.kt | 10 ++- .../server/features/transport/step/Step.kt | 1 - .../step/head/{StepHead.kt => BranchHead.kt} | 10 +-- .../transport/step/head/HeadHolder.kt | 2 +- .../head/{MultiHead.kt => MultiBranchHead.kt} | 8 ++- .../{SingleHead.kt => SingleBranchHead.kt} | 4 +- .../step/head/power/MultiPowerBranchHead.kt | 18 +++++ .../step/head/power/MultiPowerHead.kt | 18 ----- .../{PowerStepHead.kt => PowerBranchHead.kt} | 2 +- ...ePowerHead.kt => SinglePowerBranchHead.kt} | 21 +++--- .../features/transport/step/new/NewStep.kt | 13 +++- .../step/origin/ExtractorPowerOrigin.kt | 18 ++++- .../transport/step/origin/PowerOrigin.kt | 7 ++ .../transport/step/origin/SolarPowerOrigin.kt | 11 ++- .../transport/step/result/ChangeHead.kt | 12 ++++ .../result/{ChangeStep.kt => EndBranch.kt} | 8 +-- .../transport/step/result/MoveForward.kt | 33 ++++++++- .../transport/step/result/StepResult.kt | 2 +- 29 files changed, 296 insertions(+), 249 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/{StepHead.kt => BranchHead.kt} (69%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/{MultiHead.kt => MultiBranchHead.kt} (77%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/{SingleHead.kt => SingleBranchHead.kt} (68%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/{PowerStepHead.kt => PowerBranchHead.kt} (76%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/{SinglePowerHead.kt => SinglePowerBranchHead.kt} (71%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/{ChangeStep.kt => EndBranch.kt} (51%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt index 2bfa7e6e18..0843a9db56 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt @@ -4,8 +4,8 @@ import kotlinx.serialization.Serializable @Serializable data class TransportConfiguration( - val extractorTickIntervalMS: Long, - val maxPowerRemovedPerExtractorTick: Int + val extractorTickIntervalMS: Long = 2000, + val maxPowerRemovedPerExtractorTick: Int = 1000 ) { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index aaedc37506..453cec6427 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -94,18 +94,10 @@ interface TransportNode : PDCSerializable, destination: PowerInputNode, transferred: Int) {} companion object : PersistentDataType { override fun getPrimitiveType() = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 8fe90a565d..067f45d839 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -6,17 +6,19 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.data.Directional import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode { +class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode, IntermediateNode { constructor(network: ChunkPowerNetwork, origin: Long) : this(network) { positions.add(origin) } @@ -25,7 +27,7 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode + return node !is SourceNode<*> } override fun loadData(persistentDataContainer: PersistentDataContainer) { @@ -49,24 +51,14 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode): StepResult { // Simply move on to the next node - PowerTransportStep( - step.origin, - step.steps, - next, - step, - step.traversedNodes - ).invoke() + return MoveForward() } + override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it) } + .firstOrNull() + override fun toString(): String = "(END ROD NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt index c6ccebc8ba..a9b6d702e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -4,17 +4,19 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class MergeNode(override val network: ChunkPowerNetwork) : SingleNode { +class MergeNode(override val network: ChunkPowerNetwork) : SingleNode, IntermediateNode { override val relationships: MutableSet = ObjectOpenHashSet() override var position: BlockKey by Delegates.notNull() @@ -22,27 +24,17 @@ class MergeNode(override val network: ChunkPowerNetwork) : SingleNode { this.position = position } - override suspend fun handleStep(step: Step) { - // This is not an origin node, so we can assume that it is not an origin step - step as PowerTransportStep - - val next = getTransferableNodes() - .filterNot { step.traversedNodes.contains(it) } - .filterNot { step.previous.currentNode == it } - .randomOrNull() ?: return - + override suspend fun handleHeadStep(head: BranchHead): StepResult { // Simply move on to the next node - PowerTransportStep( - step.origin, - step.steps, - next, - step, - step.traversedNodes - ).invoke() + return MoveForward() } + override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it) } + .randomOrNull() + override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode + return node !is SourceNode<*> } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 37f18d2076..adf21f3e51 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -7,21 +7,20 @@ import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerExtractorOriginStep -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import java.util.concurrent.atomic.AtomicInteger -import kotlin.math.min import kotlin.math.roundToInt import kotlin.properties.Delegates -class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, SourceNode { +class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, SourceNode { override var position by Delegates.notNull() constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { @@ -34,7 +33,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, override fun isTransferableTo(node: TransportNode): Boolean { if (node is PowerInputNode) return false - return node !is SourceNode + return node !is SourceNode<*> } override fun storeData(persistentDataContainer: PersistentDataContainer) { @@ -71,33 +70,32 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, } } - override suspend fun handleStep(step: Step) { - // Nothing can transfer to extractors - step as PowerExtractorOriginStep - - val next = getTransferableNodes().randomOrNull() ?: return - - // Simply move on to the next node - PowerTransportStep(step, step.steps, next, step, step.traversedNodes).invoke() + private var lastTicked: Long = System.currentTimeMillis() + fun markTicked() { + lastTicked = System.currentTimeMillis() } - var lastTicked: Long = System.currentTimeMillis() - - override suspend fun startStep(): PowerExtractorOriginStep? { + override suspend fun startStep(): NewStep? { + lastTicked = System.currentTimeMillis() if (extractableNodes.isEmpty()) return null - val limit = getTransferPower() - val extractablePowerPool = extractableNodes.flatMap { it.getPoweredMultiblocks() } - val sum = extractablePowerPool.sumOf { it.getPower() } - - if (sum == 0) return null - - val extractablePower = min(sum, limit) - - return PowerExtractorOriginStep(AtomicInteger(), this, extractablePower, extractablePowerPool) + if (extractablePowerPool.all { it.isEmpty() }) return null + + return NewStep( + network = this.network, + origin = getOriginData() + ) { + SinglePowerBranchHead( + holder = this, + currentNode = this@PowerExtractorNode, + share = 1.0, + ) + } } + override suspend fun getOriginData(): StepOrigin = ExtractorPowerOrigin(this) + fun getTransferPower(): Int { val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 96c3129530..c3a596ac03 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -4,10 +4,12 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component @@ -15,7 +17,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { +class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, IntermediateNode { // The position will always be set override var position by Delegates.notNull() @@ -26,7 +28,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { override val relationships: MutableSet = ObjectOpenHashSet() override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode + return node !is SourceNode<*> } override fun storeData(persistentDataContainer: PersistentDataContainer) { @@ -37,33 +39,21 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } - override suspend fun handleStep(step: Step) { - // This is not an origin node, so we can assume that it is not an origin step - step as PowerTransportStep - - val next = getTransferableNodes() - .filterNot { step.traversedNodes.contains(it) } - .filterNot { step.previous.currentNode == it } - .randomOrNull() ?: return - + override suspend fun handleHeadStep(head: BranchHead): StepResult { // Simply move on to the next node - PowerTransportStep( - step.origin, - step.steps, - next, - step, - step.traversedNodes - ).invoke() + return MoveForward() } + override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it) } + .randomOrNull() + private var lastStepped: Long = System.currentTimeMillis() private val STORED_AVERAGES = 20 private val averages = mutableListOf() - override suspend fun onCompleteChain(final: Step, destination: PowerInputNode, transferred: Int) { - final as PowerTransportStep - + override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { addAverage(TransferredPower(transferred, System.currentTimeMillis())) network.world.sendMessage(Component.text("Running average transferred is ${calculateAverage()}")) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index ad8f8448ac..1941367e4b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -6,9 +6,12 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultibl import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin +import net.horizonsend.ion.server.features.transport.step.origin.PowerOrigin import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -20,7 +23,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { +class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, DestinationNode { constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -59,42 +62,6 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { } } - override suspend fun handleStep(step: Step) { - step.traversedNodes.add(this) - - // This is not an origin node, so we can assume that it is not an origin step - step as PowerTransportStep - - val origin = step.origin - val multis = getPoweredMultiblocks() -// println("Multis before: $multis") - val destinationMultiblock = multis - .filter { it as MultiblockEntity; !it.removed } - .randomOrNull() ?: return // println("No multis! origin: $origin") - - val room = destinationMultiblock.maxPower - destinationMultiblock.getPower() - val power = origin.finishExtraction(step, room) - -// println("Finished extraction, returned $power power") - - destinationMultiblock.addPower(power) - -// println("Traversed nodes: ${step.traversedNodes}") - step.traversedNodes.forEach { - it.onCompleteChain(step, this, power) - } - - if (step.origin.currentNode is SolarPanelNode) return - -// println(""" -// Reached multiblock input -// Origin: $origin -// -// Selected $destinationMultiblock -// Added $power to $destinationMultiblock -// """.trimIndent()) - } - companion object { private val offsets = setOf( // most multiblocks have the sign a block up and out of the computer @@ -110,5 +77,31 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode { ) } + override suspend fun finishChain(head: BranchHead) { + head.setDead() + val origin = (head.holder as NewStep).origin + + val multis = getPoweredMultiblocks() + + val destinationMultiblock = multis + .filter { it as MultiblockEntity; !it.removed } + .randomOrNull() ?: return // println("No multis! origin: $origin") + + val power: Int = when (origin) { + is PowerOrigin -> origin.getTransferPower(destinationMultiblock) + else -> throw NotImplementedError("Unknown power origin $origin") + } + +// println("Finished extraction, returned $power power") + + val remainder = if (origin is ExtractorPowerOrigin) origin.removeOrigin(power) else 0 + destinationMultiblock.addPower(power - remainder) + +// println("Traversed nodes: ${step.traversedNodes}") + head.previousNodes.forEach { + it.onCompleteChain(head, this, power) + } + } + override fun toString(): String = "POWER INPUT NODE: ${getPoweredMultiblocks().toList().size} powered multiblocks, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index b82fdac2c8..28008055d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -6,11 +6,15 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.SolarPowerOriginStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.origin.SolarPowerOrigin +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -21,7 +25,6 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LONG_ARRAY -import java.util.concurrent.atomic.AtomicInteger import java.util.function.Consumer import kotlin.math.PI import kotlin.math.max @@ -30,7 +33,11 @@ import kotlin.math.sin /** * Represents a solar panel, or multiple **/ -class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode, SourceNode { +class SolarPanelNode( + override val network: ChunkPowerNetwork +) : MultiNode, + SourceNode, + IntermediateNode { override val positions: MutableSet = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() @@ -215,34 +222,36 @@ class SolarPanelNode(override val network: ChunkPowerNetwork) : MultiNode() - .shuffled() // Make sure the lowest priority, if multiple is random every time - .minByOrNull { it.exitDistance } - } + override suspend fun getOriginData(): SolarPowerOrigin = SolarPowerOrigin(this) - // Solar panel pathfinding logic: - // Find the closest exit from the solar fiend and transfer to it - override suspend fun handleStep(step: Step) { - val next = findClosestOrExit() ?: return + override suspend fun startStep(): NewStep? { + val power = getPower() + if (power <= 0) return null - when (step) { - is PowerTransportStep -> PowerTransportStep(step.origin, step.steps, next, step, step.traversedNodes) - is SolarPowerOriginStep -> PowerTransportStep(step, step.steps, next, step, step.traversedNodes) - else -> throw NotImplementedError("Unrecognized step type $step") - }.invoke() + return NewStep( + network = this.network, + origin = getOriginData() + ) { + SinglePowerBranchHead( + holder = this, + currentNode = this@SolarPanelNode, + share = 1.0, + ) + } } - override suspend fun startStep(): SolarPowerOriginStep? { - val power = tickAndGetPower() - if (power <= 0) return null - -// println("Starting solar step") + override suspend fun handleHeadStep(head: BranchHead): StepResult { + // Simply move on to the next node + return MoveForward() + } - return SolarPowerOriginStep(AtomicInteger(), this, power) + override suspend fun getNextNode(head: BranchHead): TransportNode? { + val neighbors = getTransferableNodes() + return neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: + neighbors + .filterIsInstance() + .shuffled() // Make sure the lowest priority, if multiple is random every time + .minByOrNull { it.exitDistance } } override fun loadIntoNetwork() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 1136950f4e..122e4fc847 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -5,10 +5,12 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.PowerTransportStep -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer @@ -19,7 +21,7 @@ import org.bukkit.persistence.PersistentDataType * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode { +class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode, IntermediateNode { constructor(network: ChunkPowerNetwork, origin: BlockKey) : this(network) { positions.add(origin) } @@ -29,7 +31,7 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode = ObjectOpenHashSet() override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode + return node !is SourceNode<*> } override fun loadData(persistentDataContainer: PersistentDataContainer) { @@ -54,24 +56,14 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode): StepResult { // Simply move on to the next node - PowerTransportStep( - step.origin, - step.steps, - next, - step, - step.traversedNodes - ).invoke() + return MoveForward() } + override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it) } + .firstOrNull() + override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt index 6db77be95a..ae41475486 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.StepHead +import net.horizonsend.ion.server.features.transport.step.head.BranchHead interface DestinationNode { - suspend fun finishChain(head: StepHead) + suspend fun finishChain(head: BranchHead) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt index 39fdd91009..803b3c819c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt @@ -1,7 +1,8 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.StepHead +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.result.StepResult interface IntermediateNode { @@ -11,5 +12,7 @@ interface IntermediateNode { * This may create a new step for a single node, spawn off multiple steps, or more * Each node defines how it is stepped. **/ - suspend fun handleHeadStep(head: StepHead): StepResult + suspend fun handleHeadStep(head: BranchHead): StepResult + + suspend fun getNextNode(head: BranchHead): TransportNode? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt index 1407aaf53d..8be78aaf89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt @@ -1,12 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.step.OriginStep +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin /** * Representing the start of a power system * * Nodes may not transfer into a source node **/ -interface SourceNode { - suspend fun startStep(): OriginStep? +interface SourceNode { + suspend fun getOriginData(): StepOrigin + + suspend fun startStep(): NewStep? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index df246c8123..dc64e8ab4f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -12,7 +12,6 @@ interface Step { if (steps.incrementAndGet() > MAX_DEPTH) return traversedNodes.add(currentNode) - currentNode.handleStep(this) // println(""" // Step has been invoked diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt index a2bcf3dd0f..3b6f457a96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/StepHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt @@ -2,15 +2,12 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.new.NewStep -interface StepHead { +interface BranchHead { val holder: HeadHolder - val parent: NewStep - var currentNode: TransportNode /** Nodes that this head has covered */ - val coveredNodes: MutableSet + val previousNodes: MutableSet /** * Moves this step forward @@ -20,4 +17,7 @@ interface StepHead { /** Returns whether this head is dead */ fun isDead(): Boolean + + /** Sets this branch to be dead */ + fun setDead() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt index ed1aebb675..44deac1d17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt @@ -3,5 +3,5 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork interface HeadHolder { - var head: StepHead + var head: BranchHead } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt similarity index 77% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt index 5ef91c09e0..5ada84ca05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt @@ -3,11 +3,11 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork /** A head which branches into multiple sub-heads */ -interface MultiHead : StepHead { +interface MultiBranchHead : BranchHead { val heads: MutableSet> /** Holder that allows the head within to be replaced */ - class MultiHeadHolder(override var head: StepHead) : HeadHolder + class MultiHeadHolder(override var head: BranchHead) : HeadHolder // Just pass it forward override suspend fun stepForward() { @@ -18,4 +18,8 @@ interface MultiHead : StepHead { override fun isDead(): Boolean { return heads.all { it.head.isDead() } } + + override fun setDead() { + heads.forEach { it.head.setDead() } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt similarity index 68% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt index 8efbb0fd4b..9b40d382e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt @@ -3,6 +3,6 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -interface SingleHead : StepHead { - var head: TransportNode +interface SingleBranchHead : BranchHead { + var currentNode: TransportNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt new file mode 100644 index 0000000000..db24d40f4d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.transport.step.head.power + +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead + +/** + * + * + **/ +class MultiPowerBranchHead( + override val holder: HeadHolder, + override val share: Double, + override val previousNodes: MutableSet = mutableSetOf(), + override val heads: MutableSet> = mutableSetOf(), +) : MultiBranchHead, PowerBranchHead + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt deleted file mode 100644 index 5d4af4c221..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerHead.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.power - -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.head.MultiHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep - -/** - * - * - **/ -class MultiPowerHead( - override val share: Double, - override val parent: NewStep, - override val coveredNodes: MutableSet = mutableSetOf(), - override val heads: MutableSet> = mutableSetOf() -) : MultiHead, PowerStepHead - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt similarity index 76% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt index b50553b226..4af2a1afff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerStepHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt @@ -1,5 +1,5 @@ package net.horizonsend.ion.server.features.transport.step.head.power -interface PowerStepHead { +interface PowerBranchHead { val share: Double } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt similarity index 71% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index dac2b5c462..1554f23be3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -6,27 +6,24 @@ import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwo import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode +import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.SingleHead -import net.horizonsend.ion.server.features.transport.step.head.StepHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead /** * Transferred power down a single path. * * **/ -class SinglePowerHead( +class SinglePowerBranchHead( override val holder: HeadHolder, - override var head: TransportNode, - override val parent: NewStep, + override var currentNode: TransportNode, override val share: Double, - override val coveredNodes: MutableSet = mutableSetOf(), - override var currentNode: TransportNode -) : SingleHead, PowerStepHead { + override val previousNodes: MutableSet = mutableSetOf() +) : SingleBranchHead, PowerBranchHead { private var isDead = false - private fun setDead() { + override fun setDead() { isDead = true } @@ -35,11 +32,11 @@ class SinglePowerHead( override suspend fun stepForward() { val node = currentNode - if (tryCast>(node) { finishChain(this@SinglePowerHead) }) return + if (tryCast>(node) { finishChain(this@SinglePowerBranchHead) }) return node as IntermediateNode - val result = node.handleHeadStep(this as StepHead) + val result = node.handleHeadStep(this as BranchHead) result.apply(holder as HeadHolder) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt index fa0dcf3c0e..32af370e34 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt @@ -1,15 +1,24 @@ package net.horizonsend.ion.server.features.transport.step.new import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.StepHead import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class NewStep( val network: T, val origin: StepOrigin, - override var head: StepHead, ) : HeadHolder { + override lateinit var head: BranchHead + + constructor(network: T, origin: StepOrigin, getHead: NewStep.() -> BranchHead) : this(network, origin) { + this.head = getHead() + } + + constructor(network: T, origin: StepOrigin, head: BranchHead) : this(network, origin) { + this.head = head + } + suspend operator fun invoke() { while (!head.isDead()) { head.stepForward() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt index 377eab62e5..37cfd36583 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt @@ -1,12 +1,13 @@ package net.horizonsend.ion.server.features.transport.step.origin import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode class ExtractorPowerOrigin( val origin: PowerExtractorNode -) : StepOrigin { +) : StepOrigin, PowerOrigin { /** * Remove power from the origin extractor's multiblocks. * @@ -55,4 +56,19 @@ class ExtractorPowerOrigin( return removeRemaining } + + private fun getAvailablePower(): Int = origin.extractableNodes + .flatMap { it.getPoweredMultiblocks() } + .distinct() + .filterNot { (it as MultiblockEntity).removed } + .sumOf { it.getPower() } + + fun finish() { + origin.markTicked() + } + + override fun getTransferPower(destination: PoweredMultiblockEntity): Int { + val room = destination.maxPower - destination.getPower() + return minOf(room, origin.getTransferPower(), getAvailablePower()) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt new file mode 100644 index 0000000000..023b65f6c4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.step.origin + +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity + +interface PowerOrigin { + fun getTransferPower(destination: PoweredMultiblockEntity): Int +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt index 0affc4eec3..09b4d6c79e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt @@ -1,6 +1,15 @@ package net.horizonsend.ion.server.features.transport.step.origin +import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin +class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin, PowerOrigin { + override fun getTransferPower(destination: PoweredMultiblockEntity): Int { + val room = destination.maxPower - destination.getPower() + val power = origin.tickAndGetPower() + + // No max transfer limit for solar fields, as large ones would quickly overwhelm any limit + return minOf(power, room) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt new file mode 100644 index 0000000000..d92846af53 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt @@ -0,0 +1,12 @@ +package net.horizonsend.ion.server.features.transport.step.result + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder + +/** A result which changes the head of the step to a new one */ +class ChangeHead(val new: BranchHead) : StepResult { + override suspend fun apply(headHolder: HeadHolder) { + headHolder.head = new + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt similarity index 51% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt index bbffb5dab1..ba530db80d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeStep.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt @@ -2,10 +2,10 @@ package net.horizonsend.ion.server.features.transport.step.result import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.StepHead -class ChangeHead(val new: StepHead) : StepResult { - override fun apply(head: HeadHolder) { - head.head = new +/** A result which marks the branch as dead */ +class EndBranch : StepResult { + override suspend fun apply(headHolder: HeadHolder) { + headHolder.head.setDead() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt index 70aafa13a6..9a10aa37d9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt @@ -1,10 +1,39 @@ package net.horizonsend.ion.server.features.transport.step.result import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.type.DestinationNode +import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +/** A result which moves the head of the branch forward, using the current node's pathfinding */ class MoveForward : StepResult { - override fun apply(head: HeadHolder) { - val currentNode = head.head.currentNode + override suspend fun apply(headHolder: HeadHolder) { + val branchHead = headHolder.head + + tryCast>(branchHead) { + val next = getNextNode(headHolder.head) ?: return EndBranch().apply(headHolder) + + if (branchHead is SingleBranchHead<*>) { + branchHead.currentNode = next + } + } + + tryCast>(branchHead) { + finishChain(headHolder.head) + } + + if (branchHead is SourceNode<*>) throw NotImplementedError() + } + + // Get around runtime type erasure + private inline fun tryCast(instance: Any?, block: T.() -> Unit): Boolean { + if (instance is T) { + block(instance) + return true + } + + return false } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt index 11faa90ec3..8d851d2abc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt @@ -4,6 +4,6 @@ import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwo import net.horizonsend.ion.server.features.transport.step.head.HeadHolder interface StepResult { - fun apply(head: HeadHolder) + suspend fun apply(headHolder: HeadHolder) } From 65ca7f7fb883722273662a5180abb340dedd2945 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 27 Jun 2024 00:32:32 -0500 Subject: [PATCH 072/500] easy brightness checking --- .../features/transport/node/power/SolarPanelNode.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 28008055d4..0e24709398 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -19,6 +19,12 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.core.BlockPos +import net.minecraft.world.level.LightLayer import org.bukkit.GameRule import org.bukkit.Material import org.bukkit.World @@ -59,6 +65,13 @@ class SolarPanelNode( * Returns the amount of power between ticks **/ fun getPower(): Int { + // Sample position + val sample = positions.first() + val pos = BlockPos(getX(sample), getY(sample), getZ(sample)) + val lightLevel = network.world.minecraft.getBrightness(LightLayer.SKY, pos) + + if (lightLevel == 0) return 0 + val daylightMultiplier: Double = if ( network.world.environment == World.Environment.NORMAL && network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true From d087b7abf08f23ff7e2d83c60f0819572167206d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 28 Jun 2024 00:52:54 -0500 Subject: [PATCH 073/500] fixes --- .../server/command/admin/IonChunkCommand.kt | 1 + .../entity/type/PoweredMultiblockEntity.kt | 3 ++- .../transport/node/power/EndRodNode.kt | 4 ++-- .../transport/node/power/MergeNode.kt | 4 ++-- .../node/power/PowerExtractorNode.kt | 18 ++++++++++++++-- .../transport/node/power/PowerFlowMeter.kt | 4 ++-- .../transport/node/power/PowerInputNode.kt | 2 +- .../transport/node/power/SolarPanelNode.kt | 21 +++++++++++-------- .../transport/node/power/SpongeNode.kt | 4 ++-- .../transport/node/type/SourceNode.kt | 4 ++-- .../{IntermediateNode.kt => StepHandler.kt} | 2 +- .../transport/step/head/BranchHead.kt | 2 +- .../transport/step/head/MultiBranchHead.kt | 4 ++-- .../step/head/power/SinglePowerBranchHead.kt | 14 ++++++++++--- .../features/transport/step/new/NewStep.kt | 4 ++++ .../transport/step/result/EndBranch.kt | 2 +- .../transport/step/result/MoveForward.kt | 20 ++++++++++++------ 17 files changed, 76 insertions(+), 37 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/{IntermediateNode.kt => StepHandler.kt} (92%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index ca6c102a17..0f7cf4945e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -89,6 +89,7 @@ object IonChunkCommand : SLCommand() { when (grid) { is ChunkPowerNetwork -> { sender.information("${grid.solarPanels.size} solar panels") + sender.information("${grid.extractors.size} extractors") sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index ef0afc2395..566b59425f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.front import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -83,7 +84,7 @@ interface PoweredMultiblockEntity { //TODO replace this require(this is MultiblockEntity) Tasks.sync { - val sign = getSign() ?: return@sync println("Tried to update visual on a multiblock without an intact sign") + val sign = getSign() ?: return@sync println("Tried to update visual on a multiblock without an intact sign : ${world.name} ${toVec3i(position)}") sign.front().line(2, formatPower()) sign.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 067f45d839..92c303b21a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -6,9 +6,9 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult @@ -18,7 +18,7 @@ import org.bukkit.block.data.Directional import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode, IntermediateNode { +class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode, StepHandler { constructor(network: ChunkPowerNetwork, origin: Long) : this(network) { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt index a9b6d702e6..45a09b3905 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -4,9 +4,9 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult @@ -16,7 +16,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class MergeNode(override val network: ChunkPowerNetwork) : SingleNode, IntermediateNode { +class MergeNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { override val relationships: MutableSet = ObjectOpenHashSet() override var position: BlockKey by Delegates.notNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index adf21f3e51..42872996da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -7,10 +7,13 @@ import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead import net.horizonsend.ion.server.features.transport.step.new.NewStep import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -84,7 +87,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, return NewStep( network = this.network, - origin = getOriginData() + origin = getOriginData() ?: return null ) { SinglePowerBranchHead( holder = this, @@ -94,7 +97,18 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, } } - override suspend fun getOriginData(): StepOrigin = ExtractorPowerOrigin(this) + override suspend fun getNextNode(head: BranchHead): TransportNode? { + return getTransferableNodes().randomOrNull() + } + + override suspend fun handleHeadStep(head: BranchHead): StepResult { + return MoveForward() + } + + override suspend fun getOriginData(): StepOrigin? { + if (getTransferableNodes().isEmpty()) return null + return ExtractorPowerOrigin(this) + } fun getTransferPower(): Int { val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index c3a596ac03..63ac0babf6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -4,9 +4,9 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult @@ -17,7 +17,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, IntermediateNode { +class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { // The position will always be set override var position by Delegates.notNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 1941367e4b..f9851a1f1e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -78,7 +78,7 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest } override suspend fun finishChain(head: BranchHead) { - head.setDead() + head.markDead() val origin = (head.holder as NewStep).origin val multis = getPoweredMultiblocks() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 0e24709398..6b5c5fc16b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -6,9 +6,9 @@ import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead import net.horizonsend.ion.server.features.transport.step.new.NewStep @@ -43,7 +43,7 @@ class SolarPanelNode( override val network: ChunkPowerNetwork ) : MultiNode, SourceNode, - IntermediateNode { + StepHandler { override val positions: MutableSet = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() @@ -65,17 +65,18 @@ class SolarPanelNode( * Returns the amount of power between ticks **/ fun getPower(): Int { - // Sample position - val sample = positions.first() - val pos = BlockPos(getX(sample), getY(sample), getZ(sample)) - val lightLevel = network.world.minecraft.getBrightness(LightLayer.SKY, pos) - - if (lightLevel == 0) return 0 - val daylightMultiplier: Double = if ( network.world.environment == World.Environment.NORMAL && network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true ) { + // Sample position + val sample = positions.first() + val pos = BlockPos(getX(sample), getY(sample), getZ(sample)) + val lightLevel = network.world.minecraft.getBrightness(LightLayer.SKY, pos) + + if (lightLevel == 0) return 0 + + // Calculate via sine curve otherwise val daylight = sin((network.world.time / (12000.0 / PI)) - (PI / 2)) max(0.0, daylight) * 1.5 // 1.5 to bring area under curve to around equal with night } else 0.5 @@ -239,6 +240,7 @@ class SolarPanelNode( override suspend fun startStep(): NewStep? { val power = getPower() + println("Solar power was $power") if (power <= 0) return null return NewStep( @@ -263,6 +265,7 @@ class SolarPanelNode( return neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: neighbors .filterIsInstance() + .filter { it.exitDistance < this.exitDistance } // Make sure it can't move further from an exit .shuffled() // Make sure the lowest priority, if multiple is random every time .minByOrNull { it.exitDistance } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 122e4fc847..42cd5a1119 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -5,9 +5,9 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult @@ -21,7 +21,7 @@ import org.bukkit.persistence.PersistentDataType * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode, IntermediateNode { +class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode, StepHandler { constructor(network: ChunkPowerNetwork, origin: BlockKey) : this(network) { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt index 8be78aaf89..c77df81560 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt @@ -9,8 +9,8 @@ import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin * * Nodes may not transfer into a source node **/ -interface SourceNode { - suspend fun getOriginData(): StepOrigin +interface SourceNode : StepHandler { + suspend fun getOriginData(): StepOrigin? suspend fun startStep(): NewStep? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt similarity index 92% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt index 803b3c819c..6b0b238bbf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/IntermediateNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.result.StepResult -interface IntermediateNode { +interface StepHandler { /** * Handle the stepping of power through this node * diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt index 3b6f457a96..9c7d385251 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt @@ -19,5 +19,5 @@ interface BranchHead { fun isDead(): Boolean /** Sets this branch to be dead */ - fun setDead() + fun markDead() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt index 5ada84ca05..1c54b47f90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt @@ -19,7 +19,7 @@ interface MultiBranchHead : BranchHead { return heads.all { it.head.isDead() } } - override fun setDead() { - heads.forEach { it.head.setDead() } + override fun markDead() { + heads.forEach { it.head.markDead() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index 1554f23be3..2aa3e99607 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead @@ -23,21 +23,29 @@ class SinglePowerBranchHead( ) : SingleBranchHead, PowerBranchHead { private var isDead = false - override fun setDead() { + override fun markDead() { isDead = true } override fun isDead(): Boolean = isDead + @Suppress("UNCHECKED_CAST") override suspend fun stepForward() { val node = currentNode if (tryCast>(node) { finishChain(this@SinglePowerBranchHead) }) return - node as IntermediateNode + // All other nodes handle steps transferring in / out + node as StepHandler val result = node.handleHeadStep(this as BranchHead) + + println("Result was: $result") + println("before result") + println("current node : $currentNode") result.apply(holder as HeadHolder) + println("after result") + println("current node : $currentNode") } // Get around runtime type erasure diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt index 32af370e34..415aef5f00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.step.new import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class NewStep( @@ -21,6 +22,9 @@ class NewStep( suspend operator fun invoke() { while (!head.isDead()) { + println("Stepping forward. Head: $head") + println("Current head position: ${(head as? SinglePowerBranchHead)?.currentNode}") + println("Previous nodes: ${head.previousNodes}") head.stepForward() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt index ba530db80d..dacd5f1f58 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt @@ -6,6 +6,6 @@ import net.horizonsend.ion.server.features.transport.step.head.HeadHolder /** A result which marks the branch as dead */ class EndBranch : StepResult { override suspend fun apply(headHolder: HeadHolder) { - headHolder.head.setDead() + headHolder.head.markDead() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt index 9a10aa37d9..f0675804b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt @@ -2,25 +2,33 @@ package net.horizonsend.ion.server.features.transport.step.result import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.type.DestinationNode -import net.horizonsend.ion.server.features.transport.node.type.IntermediateNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead /** A result which moves the head of the branch forward, using the current node's pathfinding */ class MoveForward : StepResult { override suspend fun apply(headHolder: HeadHolder) { val branchHead = headHolder.head + println("Trying to move forward") - tryCast>(branchHead) { + if (branchHead is MultiBranchHead<*>) throw IllegalArgumentException("Multi branches can't be modified!") + + val currentNode = (branchHead as SingleBranchHead).currentNode + + tryCast>(currentNode) { + println("was step handler") val next = getNextNode(headHolder.head) ?: return EndBranch().apply(headHolder) + println("next node was $next") - if (branchHead is SingleBranchHead<*>) { - branchHead.currentNode = next - } + branchHead.previousNodes.add(branchHead.currentNode) + branchHead.currentNode = next } - tryCast>(branchHead) { + tryCast>(currentNode) { + println("was destination") finishChain(headHolder.head) } From 259af49b5572606b3048fd19aea0d8cdbce25876 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 29 Jun 2024 01:47:34 -0500 Subject: [PATCH 074/500] cleanup, reliability, working power extraction --- .../server/command/admin/IonChunkCommand.kt | 9 ++- .../multiblock/ChunkMultiblockManager.kt | 23 +++++-- .../multiblock/entity/MultiblockEntity.kt | 11 ++-- .../entity/type/PoweredMultiblockEntity.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 4 +- .../transport/ChunkTransportManager.kt | 7 ++- .../transport/network/ChunkPowerNetwork.kt | 21 +------ .../network/ChunkTransportNetwork.kt | 33 +++++++--- .../node/power/PowerExtractorNode.kt | 10 ++- .../transport/node/power/PowerInputNode.kt | 14 ++++- .../transport/step/head/BranchHead.kt | 3 +- .../step/head/power/MultiPowerBranchHead.kt | 4 +- .../step/head/power/SinglePowerBranchHead.kt | 3 +- .../step/origin/ExtractorPowerOrigin.kt | 62 ++++++++----------- .../transport/step/origin/PowerOrigin.kt | 2 + .../transport/step/origin/SolarPowerOrigin.kt | 8 ++- .../persistence/NamespacedKeys.kt | 1 + 17 files changed, 127 insertions(+), 90 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 0f7cf4945e..92fa6caebc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -84,7 +84,6 @@ object IonChunkCommand : SLCommand() { sender.information("${grid.nodes.size} covered position(s).") sender.information("${grid.nodes.values.distinct().size} unique node(s).") - sender.information("${grid.extractors.size} extractor node(s).") when (grid) { is ChunkPowerNetwork -> { @@ -111,7 +110,13 @@ object IonChunkCommand : SLCommand() { val grid = network.get(ionChunk) grid.nodes.clear() - grid.extractors.clear() + + when (grid) { + is ChunkPowerNetwork -> { + grid.extractors.clear() + grid.solarPanels.clear() + } + } for (x in ionChunk.originX ..ionChunk.originX + 15) { for (z in ionChunk.originZ..ionChunk.originZ + 15) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index cdd0347c80..ca3f9c7da7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -8,14 +8,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultibl import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import org.slf4j.LoggerFactory import java.util.concurrent.ConcurrentHashMap @@ -118,11 +118,16 @@ class ChunkMultiblockManager(val chunk: IonChunk) { * Save the multiblock data back into the chunk **/ private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = Multiblocks.multiblockCoroutineScope.launch { + val old = chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) + old?.let { + chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY, it) + } + val array = multiblockEntities.map { (_, entity) -> entity.serialize(adapterContext, entity.store()) }.toTypedArray() - chunk.inner.persistentDataContainer.set(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) + chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) } /** @@ -130,16 +135,22 @@ class ChunkMultiblockManager(val chunk: IonChunk) { **/ private fun loadMultiblocks() { val serialized = try { - chunk.inner.persistentDataContainer.get(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return + chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return } catch (e: IllegalArgumentException) { log.warn("Could not load chunks multiblocks for $chunk") if (e.message == "The found tag instance (NBTTagList) cannot store List") { log.info("Found outdated list tag, removing") - chunk.inner.persistentDataContainer.remove(NamespacedKeys.STORED_MULTIBLOCK_ENTITIES) + chunk.inner.persistentDataContainer.remove(STORED_MULTIBLOCK_ENTITIES) } - arrayOf() + arrayOf() + } catch (e: Throwable) { + // Try to load backup + chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return + } catch (e: Throwable) { + // Give up + return } for (serializedMultiblockData in serialized) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index d54e7f3db4..2559f51703 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -22,7 +22,7 @@ import org.bukkit.block.Sign * * @param multiblock The type of multiblock this entity represents * - * @param signDirection The direction to find the sign from the origin block (the block the sign is placed on) + * @param facing The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( val multiblock: Multiblock, @@ -31,7 +31,7 @@ abstract class MultiblockEntity( var y: Int, var z: Int, var world: World, - var signDirection: BlockFace + var facing: BlockFace ): PDCSerializable { /** Mark this entity as having been removed */ var removed: Boolean = false @@ -64,7 +64,7 @@ abstract class MultiblockEntity( * This data is serialized and stored on the chunk when not loaded. **/ fun store(): PersistentMultiblockData { - val store = PersistentMultiblockData(x, y, z, multiblock, signDirection) + val store = PersistentMultiblockData(x, y, z, multiblock, facing) storeAdditionalData(store) return store @@ -74,6 +74,7 @@ abstract class MultiblockEntity( * Gets the sign of this multiblock **/ fun getSign(): Sign? { + val signDirection = facing.oppositeFace val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) return getBlockIfLoaded(world, signLoc.x, signLoc.y, signLoc.z)?.state as? Sign @@ -81,7 +82,7 @@ abstract class MultiblockEntity( fun isIntact(): Boolean = multiblock.blockMatchesStructure( world.getBlockAt(x, y, z), - signDirection.oppositeFace, + facing.oppositeFace, loadChunks = false, particles = false ) @@ -90,7 +91,7 @@ abstract class MultiblockEntity( * **/ fun getBlockRelative(backFourth: Int, leftRight: Int, upDown: Int): Block { - val (x, y, z) = getRelative(vec3i, signDirection.oppositeFace, backFourth, leftRight, upDown) + val (x, y, z) = getRelative(vec3i, facing.oppositeFace, backFourth, leftRight, upDown) return world.getBlockAt(x, y, z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt index 566b59425f..d2acecd254 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt @@ -84,7 +84,7 @@ interface PoweredMultiblockEntity { //TODO replace this require(this is MultiblockEntity) Tasks.sync { - val sign = getSign() ?: return@sync println("Tried to update visual on a multiblock without an intact sign : ${world.name} ${toVec3i(position)}") + val sign = getSign() ?: throw NullPointerException("Tried to update visual on a multiblock without an intact sign : ${world.name} ${toVec3i(position)}") sign.front().line(2, formatPower()) sign.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index e81d9d9975..0228a0c7fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -70,7 +70,7 @@ object TestMultiblock : Multiblock(), EntityMultiblock = ConcurrentHashMap() + /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() override val dataVersion: Int = 0 //TODO 1 - override fun setup() { - - } - - override fun processBlockRemoval(key: Long) { manager.scope.launch { - val previousNode = nodes[key] ?: return@launch - - extractors.remove(key) - - previousNode.handleRemoval(key) - }} - - override fun processBlockAddition(key: Long, new: BlockSnapshot) { manager.scope.launch { - createNodeFromBlock(new) - }} - private suspend fun tickSolars() { for (solarPanel in solarPanels) { runCatching { solarPanel.startStep()?.invoke() }.onFailure { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index e2b6552f3d..ff036e34d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -10,7 +10,6 @@ import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES @@ -26,8 +25,9 @@ import org.bukkit.persistence.PersistentDataType import java.util.concurrent.ConcurrentHashMap abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { + protected var ready: Boolean = false + val nodes: ConcurrentHashMap = ConcurrentHashMap() - val extractors: ConcurrentHashMap = ConcurrentHashMap() val world get() = manager.chunk.world @@ -38,7 +38,19 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int - open fun setup() {} + fun finalizeNetwork() { + ready = true + } + + open fun processBlockRemoval(key: Long) { manager.scope.launch { withTransportDisabled { + val previousNode = nodes[key] ?: return@withTransportDisabled + + previousNode.handleRemoval(key) + }}} + + open fun processBlockAddition(key: Long, new: BlockSnapshot) { manager.scope.launch { + withTransportDisabled { createNodeFromBlock(new) } + }} /** * Handle the creation / loading of the node into memory @@ -46,12 +58,9 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { open suspend fun createNodeFromBlock(block: BlockSnapshot) { val key = toBlockKey(block.x, block.y, block.z) - nodeFactory.create(key, block) + withTransportDisabled { nodeFactory.create(key, block) } } - abstract fun processBlockRemoval(key: Long) - abstract fun processBlockAddition(key: Long, new: BlockSnapshot) - /** * Load stored node data from the chunk * @@ -94,12 +103,15 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.seconds().toTypedArray()) pdc.set(namespacedKey, PersistentDataType.TAG_CONTAINER, container) + pdc.set(DATA_VERSION, PersistentDataType.INTEGER, dataVersion) saveAdditional(pdc) } open fun saveAdditional(pdc: PersistentDataContainer) {} + suspend fun tickIfReady() { if (ready) tick() } + /** * **/ @@ -133,6 +145,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { buildRelations() finalizeNodes() + finalizeNetwork() } /** @@ -219,4 +232,10 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val chunk = IonChunk[world, chunkX, chunkZ] ?: return null return type.get(chunk).nodes[key] } + + protected suspend inline fun withTransportDisabled(crossinline block: suspend () -> Unit) { + ready = false + block.invoke() + ready = true + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 42872996da..90d7eeb624 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -79,13 +79,12 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, } override suspend fun startStep(): NewStep? { - lastTicked = System.currentTimeMillis() if (extractableNodes.isEmpty()) return null val extractablePowerPool = extractableNodes.flatMap { it.getPoweredMultiblocks() } if (extractablePowerPool.all { it.isEmpty() }) return null - return NewStep( + val step = NewStep( network = this.network, origin = getOriginData() ?: return null ) { @@ -95,6 +94,10 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, share = 1.0, ) } + + markTicked() + + return step } override suspend fun getNextNode(head: BranchHead): TransportNode? { @@ -112,6 +115,9 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, fun getTransferPower(): Int { val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() + println("Tick Interval: $interval") + println("MaxPerExtractorTick: ${IonServer.transportSettings.maxPowerRemovedPerExtractorTick}") + println("Delta MS: ${System.currentTimeMillis() - lastTicked}") return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index f9851a1f1e..a4557bd9ea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -9,7 +9,6 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin import net.horizonsend.ion.server.features.transport.step.origin.PowerOrigin import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS @@ -19,6 +18,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates @@ -78,8 +78,16 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest } override suspend fun finishChain(head: BranchHead) { + val origin = head.holder.origin + println(""" + FINISHING CHAIN!!!! + covered: ${head.previousNodes} + origin ${head.holder.origin} + origin loc = ${if (origin is ExtractorPowerOrigin) toVec3i(origin.extractorNode.position).toString() else ""} + end loc = ${toVec3i(position)} + """.trimIndent()) + head.markDead() - val origin = (head.holder as NewStep).origin val multis = getPoweredMultiblocks() @@ -95,6 +103,8 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest // println("Finished extraction, returned $power power") val remainder = if (origin is ExtractorPowerOrigin) origin.removeOrigin(power) else 0 + println("Remainder power was $remainder") + println("Adding ${power - remainder} to $destinationMultiblock") destinationMultiblock.addPower(power - remainder) // println("Traversed nodes: ${step.traversedNodes}") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt index 9c7d385251..4eebad4137 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt @@ -2,9 +2,10 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.step.new.NewStep interface BranchHead { - val holder: HeadHolder + val holder: NewStep /** Nodes that this head has covered */ val previousNodes: MutableSet diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt index db24d40f4d..16aff010f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt @@ -2,15 +2,15 @@ package net.horizonsend.ion.server.features.transport.step.head.power import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep /** * * **/ class MultiPowerBranchHead( - override val holder: HeadHolder, + override val holder: NewStep, override val share: Double, override val previousNodes: MutableSet = mutableSetOf(), override val heads: MutableSet> = mutableSetOf(), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index 2aa3e99607..bf59ebdedf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import net.horizonsend.ion.server.features.transport.step.new.NewStep /** * Transferred power down a single path. @@ -16,7 +17,7 @@ import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead * **/ class SinglePowerBranchHead( - override val holder: HeadHolder, + override val holder: NewStep, override var currentNode: TransportNode, override val share: Double, override val previousNodes: MutableSet = mutableSetOf() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt index 37cfd36583..6628f0f844 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt @@ -6,8 +6,9 @@ import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode class ExtractorPowerOrigin( - val origin: PowerExtractorNode + val extractorNode: PowerExtractorNode ) : StepOrigin, PowerOrigin { + override val transferLimit: Int = extractorNode.getTransferPower() /** * Remove power from the origin extractor's multiblocks. * @@ -15,60 +16,51 @@ class ExtractorPowerOrigin( **/ fun removeOrigin(amount: Int): Int { // List of multiblock entities that power may be taken from - val availableEntities = origin.extractableNodes + val availableEntities = extractorNode.extractableNodes .flatMap { it.getPoweredMultiblocks() } .distinct() .filterNotTo(mutableListOf()) { (it as MultiblockEntity).removed || it.isEmpty() } - val transportLimit = origin.getTransferPower() + val minRemove = minOf(amount, availableEntities.minOfOrNull { it.getPower() } ?: return amount) - var removeRemaining = amount + println("to remove $amount") - while (removeRemaining >= 0) { - val minRemove = availableEntities.minOfOrNull { it.getPower() } ?: break + val share = minRemove / availableEntities.size - // Remove the minimum in any of the multis, the limit of what can be removed, or the remaining power to remove. - // Whichever is lowest. - val toRemove = minOf(minRemove, transportLimit, removeRemaining) + var removeRemaining = minRemove - val share = toRemove / availableEntities.size - val remainder = toRemove - (share * availableEntities.size) + // Remove an equal share from each of the inventories + for (entity in availableEntities) { + entity as MultiblockEntity + if (entity.removed) continue - // Remove an equal share from each of the inventories - for (entity in availableEntities) { - entity as MultiblockEntity - if (entity.removed) continue - - // Should never be more than 0, but handle the possibility - val notRemoved = entity.removePower(share) - removeRemaining -= (notRemoved - share) - } - - // Remove the remainder, if able - // If not able, it can just be stuck onto the amount that couldn't be removed - availableEntities.firstOrNull { it.canRemovePower(remainder) }?.run { - removePower(remainder) - removeRemaining -= remainder - } + // Should never be more than 0, but handle the possibility + val notRemoved = entity.removePower(share) + println("Didn't remove $notRemoved") + removeRemaining -= (share - notRemoved) + println("removeRemaining: $removeRemaining") + } - availableEntities.removeAll { it.isEmpty() } + availableEntities.firstOrNull { it.canRemovePower(removeRemaining) }?.run { + removePower(removeRemaining) + removeRemaining = 0 } return removeRemaining } - private fun getAvailablePower(): Int = origin.extractableNodes + private fun getAvailablePower(): Int = extractorNode.extractableNodes .flatMap { it.getPoweredMultiblocks() } .distinct() .filterNot { (it as MultiblockEntity).removed } .sumOf { it.getPower() } - fun finish() { - origin.markTicked() - } - override fun getTransferPower(destination: PoweredMultiblockEntity): Int { - val room = destination.maxPower - destination.getPower() - return minOf(room, origin.getTransferPower(), getAvailablePower()) + val destinationCapacity = destination.maxPower - destination.getPower() + println("Room: $destinationCapacity") + println("Available: ${getAvailablePower()}") + println("Transfer limit: ${extractorNode.getTransferPower()}") + + return minOf(destinationCapacity, transferLimit, getAvailablePower()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt index 023b65f6c4..aef7731e2c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt @@ -4,4 +4,6 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultibl interface PowerOrigin { fun getTransferPower(destination: PoweredMultiblockEntity): Int + + val transferLimit: Int } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt index 09b4d6c79e..95d2da7f75 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt @@ -5,11 +5,13 @@ import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin, PowerOrigin { + override val transferLimit: Int = Int.MAX_VALUE + private val powerTransfer = origin.tickAndGetPower() + override fun getTransferPower(destination: PoweredMultiblockEntity): Int { - val room = destination.maxPower - destination.getPower() - val power = origin.tickAndGetPower() + val destinationCapacity = destination.maxPower - destination.getPower() // No max transfer limit for solar fields, as large ones would quickly overwhelm any limit - return minOf(power, room) + return minOf(powerTransfer, destinationCapacity) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index ff45f605ca..2551878584 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -85,6 +85,7 @@ object NamespacedKeys { val CARGO_CRATE = key("cargo_crate") val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") + val STORED_MULTIBLOCK_ENTITIES_OLD = key("stored_multiblock_entities_old") val EXTRACTOR_DATA = key("extractor_data") val RESOURCE_CAPACITY_MAX = key("resource_capacity_max") From aba0a6d19084412b678c4c7c29c7598416d7896d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 29 Jun 2024 01:53:12 -0500 Subject: [PATCH 075/500] remove old step --- .../node/power/PowerExtractorNode.kt | 6 +- .../transport/node/power/PowerFlowMeter.kt | 20 +++-- .../transport/node/power/SolarPanelNode.kt | 6 +- .../transport/node/type/SourceNode.kt | 4 +- .../features/transport/step/PowerStep.kt | 81 ------------------- .../server/features/transport/step/Step.kt | 62 ++++++-------- .../features/transport/step/TransferStatus.kt | 8 -- .../transport/step/head/BranchHead.kt | 4 +- .../step/head/power/MultiPowerBranchHead.kt | 4 +- .../step/head/power/SinglePowerBranchHead.kt | 4 +- .../features/transport/step/new/NewStep.kt | 31 ------- 11 files changed, 47 insertions(+), 183 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 90d7eeb624..3f0a5af2df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -7,9 +7,9 @@ import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin import net.horizonsend.ion.server.features.transport.step.result.MoveForward @@ -78,13 +78,13 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, lastTicked = System.currentTimeMillis() } - override suspend fun startStep(): NewStep? { + override suspend fun startStep(): Step? { if (extractableNodes.isEmpty()) return null val extractablePowerPool = extractableNodes.flatMap { it.getPoweredMultiblocks() } if (extractablePowerPool.all { it.isEmpty() }) return null - val step = NewStep( + val step = Step( network = this.network, origin = getOriginData() ?: return null ) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 63ac0babf6..2a97755e66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -13,11 +13,19 @@ import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { + constructor(network: ChunkPowerNetwork, direction: BlockFace) : this(network) { + this.direction = direction + } + + // The direction that the text will be displayed on + private var direction: BlockFace = BlockFace.NORTH + // The position will always be set override var position by Delegates.notNull() @@ -75,21 +83,11 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step averages[0] = average } - fun calculateAverage(): Double { -// println("Averages: $averages") - - val last = averages.first() - -// println("Last: $last") - + private fun calculateAverage(): Double { val sum = averages.sumOf { it.transferred } -// println("Transferred sum: $sum") - val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 -// println("Seconds diff $timeDiff") - return sum / timeDiff } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 6b5c5fc16b..cf5420e729 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -9,9 +9,9 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep import net.horizonsend.ion.server.features.transport.step.origin.SolarPowerOrigin import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult @@ -238,12 +238,12 @@ class SolarPanelNode( override suspend fun getOriginData(): SolarPowerOrigin = SolarPowerOrigin(this) - override suspend fun startStep(): NewStep? { + override suspend fun startStep(): Step? { val power = getPower() println("Solar power was $power") if (power <= 0) return null - return NewStep( + return Step( network = this.network, origin = getOriginData() ) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt index c77df81560..dc4e348ce9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin /** @@ -12,5 +12,5 @@ import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin interface SourceNode : StepHandler { suspend fun getOriginData(): StepOrigin? - suspend fun startStep(): NewStep? + suspend fun startStep(): Step? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt deleted file mode 100644 index 173b1a02c6..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/PowerStep.kt +++ /dev/null @@ -1,81 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step - -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.node.TransportNode -import java.util.concurrent.atomic.AtomicInteger -import kotlin.math.min -import kotlin.math.roundToInt - -data class PowerExtractorOriginStep( - override val steps: AtomicInteger, - override val currentNode: TransportNode, - val maxPower: Int, - val extractable: List, - override val traversedNodes: MutableSet = mutableSetOf(), -) : OriginStep { - override fun finishExtraction(final: TransportStep, remainingSpace: Int): Int { - if (extractable.isEmpty()) return 0 - - // Store multis that still have power - val toExtract = extractable.toMutableList() - - // The share of the origin power along this branch of the chain - val share = (final.share * maxPower).roundToInt() - - // The maximum that should be extracted - // If limited, pick the lower - val maxPower = min(remainingSpace, share) - - // Remaining power to take - var remaining = maxPower - - // Take as much as possible - while (remaining >= 0) { - // Shouldn't be null but - val nextMin = toExtract.minByOrNull { it.getPower() } ?: return 0 - - // Take an equal amount from all multis so that the first is drained - val minTake = min(remaining, nextMin.getPower() * toExtract.size) - - // Remove this amount from remaining - remaining -= minTake - - // Perform the drain - extractEqually(minTake) - - toExtract.remove(nextMin) - } - - return maxPower - remaining - } - - /** - * Extract an equal amount of power from the extractable power banks - **/ - private fun extractEqually(amount: Int) { - val n = extractable.size - - extractable.forEach { - it.removePower(amount / n) - } - } -} - -data class SolarPowerOriginStep( - override val steps: AtomicInteger, - override val currentNode: TransportNode, - val power: Int, - override val traversedNodes: MutableSet = mutableSetOf(), -) : OriginStep { - // Solar panels do not have any additional logic needed upon extraction - override fun finishExtraction(final: TransportStep, remainingSpace: Int): Int = power -} - -data class PowerTransportStep( - val origin: OriginStep, - override val steps: AtomicInteger, - override val currentNode: TransportNode, - val previous: Step, - override val traversedNodes: MutableSet, - override val share: Float = 1f -) : TransportStep diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index dc64e8ab4f..05e5c21f6a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -1,45 +1,31 @@ package net.horizonsend.ion.server.features.transport.step -import net.horizonsend.ion.server.features.transport.node.TransportNode -import java.util.concurrent.atomic.AtomicInteger - -interface Step { - val steps: AtomicInteger - val currentNode: TransportNode - val traversedNodes: MutableSet - - suspend operator fun invoke() { - if (steps.incrementAndGet() > MAX_DEPTH) return - - traversedNodes.add(currentNode) - -// println(""" -// Step has been invoked -// $steps steps taken -// currently on $currentNode -// has $share share -// traversed through $traversedNodes -// """.trimIndent()) +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin + +class Step( + val network: T, + val origin: StepOrigin, +) : HeadHolder { + override lateinit var head: BranchHead + + constructor(network: T, origin: StepOrigin, getHead: Step.() -> BranchHead) : this(network, origin) { + this.head = getHead() } - companion object { - const val MAX_DEPTH = 200 + constructor(network: T, origin: StepOrigin, head: BranchHead) : this(network, origin) { + this.head = head } -} - -/** - * A step that is the first in a chain - **/ -interface OriginStep : Step { - /** - * Removes the appropriate amount of power. Returns the amount that was removed (and is available) - * - * @param final The final step of the chain - * @param remainingSpace The limit of extraction (will use either this value or the maximum amount defined in this config, whichever is lower) - **/ - fun finishExtraction(final: TransportStep, remainingSpace: Int): Int -} -interface TransportStep : Step { - val share: Float + suspend operator fun invoke() { + while (!head.isDead()) { + println("Stepping forward. Head: $head") + println("Current head position: ${(head as? SinglePowerBranchHead)?.currentNode}") + println("Previous nodes: ${head.previousNodes}") + head.stepForward() + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt deleted file mode 100644 index 28b311b0ac..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/TransferStatus.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step - -enum class TransferStatus { - STEPPING, - SPLIT, - BLOCKED, - COMPLETE -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt index 4eebad4137..2ddaa8513c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt @@ -2,10 +2,10 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.new.NewStep +import net.horizonsend.ion.server.features.transport.step.Step interface BranchHead { - val holder: NewStep + val holder: Step /** Nodes that this head has covered */ val previousNodes: MutableSet diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt index 16aff010f2..39ce78420e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt @@ -2,15 +2,15 @@ package net.horizonsend.ion.server.features.transport.step.head.power import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep /** * * **/ class MultiPowerBranchHead( - override val holder: NewStep, + override val holder: Step, override val share: Double, override val previousNodes: MutableSet = mutableSetOf(), override val heads: MutableSet> = mutableSetOf(), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index bf59ebdedf..108a8097b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -6,10 +6,10 @@ import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwo import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.new.NewStep /** * Transferred power down a single path. @@ -17,7 +17,7 @@ import net.horizonsend.ion.server.features.transport.step.new.NewStep * **/ class SinglePowerBranchHead( - override val holder: NewStep, + override val holder: Step, override var currentNode: TransportNode, override val share: Double, override val previousNodes: MutableSet = mutableSetOf() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt deleted file mode 100644 index 415aef5f00..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/new/NewStep.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.new - -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -class NewStep( - val network: T, - val origin: StepOrigin, -) : HeadHolder { - override lateinit var head: BranchHead - - constructor(network: T, origin: StepOrigin, getHead: NewStep.() -> BranchHead) : this(network, origin) { - this.head = getHead() - } - - constructor(network: T, origin: StepOrigin, head: BranchHead) : this(network, origin) { - this.head = head - } - - suspend operator fun invoke() { - while (!head.isDead()) { - println("Stepping forward. Head: $head") - println("Current head position: ${(head as? SinglePowerBranchHead)?.currentNode}") - println("Previous nodes: ${head.previousNodes}") - head.stepForward() - } - } -} From 0e7fce35d1ab47c485b38f8e5516d5aa397ca112 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 29 Jun 2024 16:03:11 -0500 Subject: [PATCH 076/500] cleanup, fixes, remove debug println, documentation --- .../features/transport/node/TransportNode.kt | 3 +- .../transport/node/power/EndRodNode.kt | 25 +- .../transport/node/power/MergeNode.kt | 13 +- .../node/power/PowerExtractorNode.kt | 104 ++++---- .../transport/node/power/PowerFlowMeter.kt | 37 ++- .../transport/node/power/PowerInputNode.kt | 62 ++--- .../transport/node/power/SolarPanelNode.kt | 237 +++++++++--------- .../transport/node/power/SpongeNode.kt | 4 +- .../features/transport/node/type/MultiNode.kt | 2 + .../transport/node/type/SingleNode.kt | 1 + .../server/features/transport/step/Step.kt | 6 +- .../step/head/power/SinglePowerBranchHead.kt | 5 - .../step/origin/ExtractorPowerOrigin.kt | 7 - .../transport/step/result/MoveForward.kt | 4 - 14 files changed, 249 insertions(+), 261 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 453cec6427..70dd506a65 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -15,6 +15,7 @@ import org.bukkit.persistence.PersistentDataType * Represents a single node, or step, in transport transportNetwork **/ interface TransportNode : PDCSerializable { + var isDead: Boolean val network: ChunkTransportNetwork override val persistentDataType: Companion get() = Companion @@ -59,7 +60,7 @@ interface TransportNode : PDCSerializable = relationships.filter { // That this node can transfer to the other - it.sideOne.transferAllowed + it.sideOne.transferAllowed && !it.sideTwo.node.isDead }.map { it.sideTwo.node } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 92c303b21a..b103d0376a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -23,6 +23,7 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() @@ -30,14 +31,14 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode } - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } + override suspend fun handleHeadStep(head: BranchHead): StepResult { + // Simply move on to the next node + return MoveForward() } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) - } + override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it) } + .firstOrNull() override suspend fun rebuildNode(position: BlockKey) { // Create new nodes, automatically merging together @@ -51,14 +52,14 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode): StepResult { - // Simply move on to the next node - return MoveForward() + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } } - override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it) } - .firstOrNull() + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) + } override fun toString(): String = "(END ROD NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt index 45a09b3905..0e1ed39cdf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/MergeNode.kt @@ -17,24 +17,25 @@ import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class MergeNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { - override val relationships: MutableSet = ObjectOpenHashSet() + override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() + override val relationships: MutableSet = ObjectOpenHashSet() constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } - override suspend fun handleHeadStep(head: BranchHead): StepResult { - // Simply move on to the next node - return MoveForward() + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is SourceNode<*> } override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() .filterNot { head.previousNodes.contains(it) } .randomOrNull() - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> + override suspend fun handleHeadStep(head: BranchHead): StepResult { + // Simply move on to the next node + return MoveForward() } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 3f0a5af2df..49299a91c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -24,58 +24,40 @@ import kotlin.math.roundToInt import kotlin.properties.Delegates class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, SourceNode { - override var position by Delegates.notNull() - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this } + override var isDead: Boolean = false + override var position by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() + val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } + + // Region transfer + /* + * The extractor node should be allowed to transfer into any regular node. + * + * Since it does only takes from inputs, it cannot transfer into them. + * + * And it cannot transfer into any other power source + */ override fun isTransferableTo(node: TransportNode): Boolean { if (node is PowerInputNode) return false return node !is SourceNode<*> } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - - override fun loadIntoNetwork() { - super.loadIntoNetwork() - network.extractors[position] = this - } - - override suspend fun handleRemoval(position: BlockKey) { - network.extractors.remove(position) - super.handleRemoval(position) - } - - override suspend fun buildRelations(position: BlockKey) { - for (offset in ADJACENT_BLOCK_FACES) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.getNode(offsetKey) ?: continue - - if (this == neighborNode) return - - if (neighborNode is PowerInputNode) { - extractableNodes.add(neighborNode) - } - - // Add a relationship, if one should be added - addRelationship(neighborNode) - } + /* + * Nothing unique with how pathfinding is done, simply move onto a random transferable neighbor + */ + override suspend fun getNextNode(head: BranchHead): TransportNode? { + return getTransferableNodes().randomOrNull() } - private var lastTicked: Long = System.currentTimeMillis() - fun markTicked() { - lastTicked = System.currentTimeMillis() + override suspend fun handleHeadStep(head: BranchHead): StepResult { + return MoveForward() } override suspend fun startStep(): Step? { @@ -100,12 +82,9 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, return step } - override suspend fun getNextNode(head: BranchHead): TransportNode? { - return getTransferableNodes().randomOrNull() - } - - override suspend fun handleHeadStep(head: BranchHead): StepResult { - return MoveForward() + private var lastTicked: Long = System.currentTimeMillis() + fun markTicked() { + lastTicked = System.currentTimeMillis() } override suspend fun getOriginData(): StepOrigin? { @@ -115,12 +94,45 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, fun getTransferPower(): Int { val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() - println("Tick Interval: $interval") - println("MaxPerExtractorTick: ${IonServer.transportSettings.maxPowerRemovedPerExtractorTick}") - println("Delta MS: ${System.currentTimeMillis() - lastTicked}") return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() } + // End region + + // Start region loading + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } + + override fun loadIntoNetwork() { + super.loadIntoNetwork() + network.extractors[position] = this + } + + override suspend fun handleRemoval(position: BlockKey) { + network.extractors.remove(position) + super.handleRemoval(position) + } + + override suspend fun buildRelations(position: BlockKey) { + for (offset in ADJACENT_BLOCK_FACES) { + val offsetKey = getRelative(position, offset, 1) + val neighborNode = network.getNode(offsetKey) ?: continue + + if (this == neighborNode) return + + if (neighborNode is PowerInputNode) { + extractableNodes.add(neighborNode) + } + + // Add a relationship, if one should be added + addRelationship(neighborNode) + } + } override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 2a97755e66..092b746ba0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -13,40 +13,28 @@ import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { - constructor(network: ChunkPowerNetwork, direction: BlockFace) : this(network) { - this.direction = direction - } - - // The direction that the text will be displayed on - private var direction: BlockFace = BlockFace.NORTH - - // The position will always be set - override var position by Delegates.notNull() - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { this.position = position } + override var position by Delegates.notNull() + override var isDead: Boolean = false override val relationships: MutableSet = ObjectOpenHashSet() + /* + * Should transfer power like any normal node. + * + * And it cannot transfer into a source + */ override fun isTransferableTo(node: TransportNode): Boolean { return node !is SourceNode<*> } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - override suspend fun handleHeadStep(head: BranchHead): StepResult { // Simply move on to the next node return MoveForward() @@ -56,14 +44,11 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step .filterNot { head.previousNodes.contains(it) } .randomOrNull() - private var lastStepped: Long = System.currentTimeMillis() - private val STORED_AVERAGES = 20 private val averages = mutableListOf() override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { addAverage(TransferredPower(transferred, System.currentTimeMillis())) - network.world.sendMessage(Component.text("Running average transferred is ${calculateAverage()}")) } @@ -91,5 +76,13 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step return sum / timeDiff } + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } + private data class TransferredPower(val transferred: Int, val time: Long) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index a4557bd9ea..c9354642f6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -18,7 +18,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates @@ -28,21 +27,14 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest this.position = position } + override var isDead: Boolean = false override var position by Delegates.notNull() - override val relationships: MutableSet = ObjectOpenHashSet() + override fun isTransferableTo(node: TransportNode): Boolean { return node is PowerExtractorNode } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - override suspend fun buildRelations(position: BlockKey) { super.buildRelations(position) } @@ -62,30 +54,8 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest } } - companion object { - private val offsets = setOf( - // most multiblocks have the sign a block up and out of the computer - Vec3i(1, 1, 0), Vec3i(-1, 1, 0), Vec3i(0, 1, -1), Vec3i(0, 1, 1), - // power cells have it on the block - Vec3i(1, 0, 0), Vec3i(-1, 0, 0), Vec3i(0, 0, -1), Vec3i(0, 0, 1), - // drills have it on a corner - Vec3i(-1, 0, -1), Vec3i(1, 0, -1), Vec3i(1, 0, 1), Vec3i(-1, 0, 1), - // upside down mining lasers have signs below - Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), - // up and down - Vec3i(0, 1, 0), Vec3i(0, -1, 0) - ) - } - override suspend fun finishChain(head: BranchHead) { val origin = head.holder.origin - println(""" - FINISHING CHAIN!!!! - covered: ${head.previousNodes} - origin ${head.holder.origin} - origin loc = ${if (origin is ExtractorPowerOrigin) toVec3i(origin.extractorNode.position).toString() else ""} - end loc = ${toVec3i(position)} - """.trimIndent()) head.markDead() @@ -100,18 +70,36 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest else -> throw NotImplementedError("Unknown power origin $origin") } -// println("Finished extraction, returned $power power") - val remainder = if (origin is ExtractorPowerOrigin) origin.removeOrigin(power) else 0 - println("Remainder power was $remainder") - println("Adding ${power - remainder} to $destinationMultiblock") destinationMultiblock.addPower(power - remainder) -// println("Traversed nodes: ${step.traversedNodes}") head.previousNodes.forEach { it.onCompleteChain(head, this, power) } } + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } + + companion object { + private val offsets = setOf( + // most multiblocks have the sign a block up and out of the computer + Vec3i(1, 1, 0), Vec3i(-1, 1, 0), Vec3i(0, 1, -1), Vec3i(0, 1, 1), + // power cells have it on the block + Vec3i(1, 0, 0), Vec3i(-1, 0, 0), Vec3i(0, 0, -1), Vec3i(0, 0, 1), + // drills have it on a corner + Vec3i(-1, 0, -1), Vec3i(1, 0, -1), Vec3i(1, 0, 1), Vec3i(-1, 0, 1), + // upside down mining lasers have signs below + Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), + // up and down + Vec3i(0, 1, 0), Vec3i(0, -1, 0) + ) + } + override fun toString(): String = "POWER INPUT NODE: ${getPoweredMultiblocks().toList().size} powered multiblocks, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index cf5420e729..d5a4d1bed4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -1,7 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship @@ -29,8 +27,11 @@ import org.bukkit.GameRule import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.block.BlockFace.DOWN +import org.bukkit.block.BlockFace.UP import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LONG_ARRAY +import java.util.concurrent.ConcurrentHashMap import java.util.function.Consumer import kotlin.math.PI import kotlin.math.max @@ -44,23 +45,100 @@ class SolarPanelNode( ) : MultiNode, SourceNode, StepHandler { - override val positions: MutableSet = LongOpenHashSet() - override val relationships: MutableSet = ObjectOpenHashSet() + override var isDead: Boolean = false + override val positions: MutableSet = ConcurrentHashMap.newKeySet() + override val relationships: MutableSet = ConcurrentHashMap.newKeySet() /** The positions of extractors in this solar panel */ - private val extractorPositions = LongOpenHashSet() + private val extractorPositions = ConcurrentHashMap.newKeySet() /** The number of solar cells contained in this node */ private val cellNumber: Int get() = extractorPositions.size + override fun isTransferableTo(node: TransportNode): Boolean { + // Solar panels should be able to transfer through extractors and other solar panels + return node !is PowerExtractorNode + } + + override suspend fun startStep(): Step? { + val power = getPower() + if (power <= 0) return null + + return Step( + network = this.network, + origin = getOriginData() + ) { + SinglePowerBranchHead( + holder = this, + currentNode = this@SolarPanelNode, + share = 1.0, + ) + } + } + + override suspend fun handleHeadStep(head: BranchHead): StepResult { + // Simply move on to the next node + return MoveForward() + } + + override suspend fun getOriginData(): SolarPowerOrigin = SolarPowerOrigin(this) + /** * The distance this solar node is from the nearest exit of the solar field * This value will be -1 if there are no exits present **/ private var exitDistance: Int = 0 + override suspend fun getNextNode(head: BranchHead): TransportNode? { + val neighbors = getTransferableNodes() + return neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: + neighbors + .filterIsInstance() + .filter { it.exitDistance < this.exitDistance } // Make sure it can't move further from an exit + .shuffled() // Make sure the lowest priority, if multiple is random every time + .minByOrNull { it.exitDistance } + } + + /** + * Calculate the distance to an exit of a solar field + * This method is run upon neighbor unloads + **/ + private fun calculateExitDistance() { + val neighbors = getTransferableNodes() + + // Borders an exit + if (neighbors.any { it !is SolarPanelNode }) { + exitDistance = 0 + return + } + + val solars = neighbors.filterIsInstance() + if (solars.isEmpty()) { + exitDistance = -1 + return + } + + exitDistance = solars.minOf { it.exitDistance } + 1 + } + + /** + * Store the last time this node successfully transferred power, so that a difference can be gained. + * + * This will be used to calculate the amount of power generated, so it remains consistent, even in laggy conditions. + **/ private var lastTicked: Long = System.currentTimeMillis() + /** + * Get the power and reset the last ticked time + **/ + fun tickAndGetPower(): Int { + val power = getPower() + + lastTicked = System.currentTimeMillis() + + return power + } + /** * Returns the amount of power between ticks **/ @@ -87,39 +165,6 @@ class SolarPanelNode( return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() } - /** - * Get the power and reset the last ticked time - **/ - fun tickAndGetPower(): Int { - val power = getPower() - - lastTicked = System.currentTimeMillis() - - return power - } - - /** - * Calculate the distance to an exit of a solar field - * This method is run upon neighbor unloads - **/ - private fun calculateExitDistance() { - val neighbors = getTransferableNodes() - - // Borders an exit - if (neighbors.any { it !is SolarPanelNode }) { - exitDistance = 0 - return - } - - val solars = neighbors.filterIsInstance() - if (solars.isEmpty()) { - exitDistance = -1 - return - } - - exitDistance = solars.minOf { it.exitDistance } + 1 - } - /** * Execute the provided consumer across every interconnected solar node * @@ -130,6 +175,8 @@ class SolarPanelNode( consumer.accept(this) + visited.add(this) + getTransferableNodes().filterIsInstance().filterNot { visited.contains(it) }.forEach(consumer) } @@ -147,46 +194,20 @@ class SolarPanelNode( super.buildRelations(position) } - override fun isTransferableTo(node: TransportNode): Boolean { - // Solar panels should be able to transfer through extractors and other solar panels - return node !is PowerExtractorNode - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) - persistentDataContainer.set(SOLAR_CELL_EXTRACTORS, LONG_ARRAY, extractorPositions.toLongArray()) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - - val extractors = persistentDataContainer.get(SOLAR_CELL_EXTRACTORS, LONG_ARRAY) - extractors?.let { extractorPositions.addAll(it.asIterable()) } - } - override suspend fun handleRemoval(position: BlockKey) { - // Need to handle the extractor positions manually - when { - // Removed extractor, easier to find - extractorPositions.contains(position) -> removePosition( - position, - listOf(getRelative(position, BlockFace.UP, 1), getRelative(position, BlockFace.UP, 2)) - ) + isDead = true + + removePosition(position) - // Need to find extractor, search downward form position - else -> { - val extractorPosition: BlockKey = (0..2).firstNotNullOf { y -> - getRelative(position, BlockFace.DOWN, y).takeIf { extractorPositions.contains(it) } - } - - removePosition( - extractorPosition, - listOf(getRelative(extractorPosition, BlockFace.UP, 1), getRelative(extractorPosition, BlockFace.UP, 2)) - ) - } + // Remove all positions + positions.forEach { + network.nodes.remove(it) } + // Rebuild relations after cleared + clearRelations() + + // Rebuild the node without the lost position rebuildNode(position) } @@ -196,23 +217,32 @@ class SolarPanelNode( // Make sure there isn't still an extractor network.extractors.remove(extractorKey) addPosition(extractorKey) + buildRelations(extractorKey) positions += others + for (position: BlockKey in positions) { network.nodes[position] = this + buildRelations(position) } return this } - private fun removePosition(extractorKey: BlockKey, others: Iterable) { - extractorPositions -= extractorKey - positions.remove(extractorKey) - network.nodes.remove(extractorKey) - positions.removeAll(others.toSet()) + private fun removePosition(axisPosition: BlockKey) { + val extractorPos = if (extractorPositions.contains(axisPosition)) axisPosition else (1..2).firstNotNullOf { offset -> + getRelative(axisPosition, DOWN, offset).takeIf { extractorPositions.contains(it) } + } + + val otherPositions = (1..2).map { getRelative(extractorPos, UP, it) } - for (position: BlockKey in others) { - network.nodes.remove(position) + positions.remove(extractorPos) + extractorPositions.remove(extractorPos) + network.nodes.remove(extractorPos) + + for (otherPos: BlockKey in otherPositions) { + positions.remove(otherPos) + network.nodes.remove(otherPos) } } @@ -220,7 +250,7 @@ class SolarPanelNode( network.solarPanels.remove(this) // Create new nodes, automatically merging together - positions.forEach { + extractorPositions.forEach { network.nodeFactory.addSolarPanel(it, handleRelationships = false) } @@ -236,43 +266,22 @@ class SolarPanelNode( new.extractorPositions.addAll(extractorPositions) } - override suspend fun getOriginData(): SolarPowerOrigin = SolarPowerOrigin(this) - - override suspend fun startStep(): Step? { - val power = getPower() - println("Solar power was $power") - if (power <= 0) return null - - return Step( - network = this.network, - origin = getOriginData() - ) { - SinglePowerBranchHead( - holder = this, - currentNode = this@SolarPanelNode, - share = 1.0, - ) - } + override fun loadIntoNetwork() { + super.loadIntoNetwork() + network.solarPanels += this } - override suspend fun handleHeadStep(head: BranchHead): StepResult { - // Simply move on to the next node - return MoveForward() + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) + persistentDataContainer.set(SOLAR_CELL_EXTRACTORS, LONG_ARRAY, extractorPositions.toLongArray()) } - override suspend fun getNextNode(head: BranchHead): TransportNode? { - val neighbors = getTransferableNodes() - return neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: - neighbors - .filterIsInstance() - .filter { it.exitDistance < this.exitDistance } // Make sure it can't move further from an exit - .shuffled() // Make sure the lowest priority, if multiple is random every time - .minByOrNull { it.exitDistance } - } + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } - override fun loadIntoNetwork() { - super.loadIntoNetwork() - network.solarPanels += this + val extractors = persistentDataContainer.get(SOLAR_CELL_EXTRACTORS, LONG_ARRAY) + extractors?.let { extractorPositions.addAll(it.asIterable()) } } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 42cd5a1119..7ab66a0624 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -26,8 +26,8 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode = LongOpenHashSet() - + override var isDead: Boolean = false + override val positions: MutableSet = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() override fun isTransferableTo(node: TransportNode): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 61293fe258..be718b8ea6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -76,6 +76,8 @@ interface MultiNode, Z: MultiNode> : Transport } override suspend fun handleRemoval(position: BlockKey) { + isDead = true + // Remove the position from the network network.nodes.remove(position) // Remove the position from this node diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 2ce254e18e..05d22188b5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -32,6 +32,7 @@ interface SingleNode : TransportNode { } override suspend fun handleRemoval(position: BlockKey) { + isDead = true network.nodes.remove(position) clearRelations() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index 05e5c21f6a..63bc2510d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -3,10 +3,9 @@ package net.horizonsend.ion.server.features.transport.step import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin -class Step( +class Step private constructor( val network: T, val origin: StepOrigin, ) : HeadHolder { @@ -22,9 +21,6 @@ class Step( suspend operator fun invoke() { while (!head.isDead()) { - println("Stepping forward. Head: $head") - println("Current head position: ${(head as? SinglePowerBranchHead)?.currentNode}") - println("Previous nodes: ${head.previousNodes}") head.stepForward() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index 108a8097b4..3166544f58 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -41,12 +41,7 @@ class SinglePowerBranchHead( val result = node.handleHeadStep(this as BranchHead) - println("Result was: $result") - println("before result") - println("current node : $currentNode") result.apply(holder as HeadHolder) - println("after result") - println("current node : $currentNode") } // Get around runtime type erasure diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt index 6628f0f844..b6cbec23d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt @@ -23,8 +23,6 @@ class ExtractorPowerOrigin( val minRemove = minOf(amount, availableEntities.minOfOrNull { it.getPower() } ?: return amount) - println("to remove $amount") - val share = minRemove / availableEntities.size var removeRemaining = minRemove @@ -36,9 +34,7 @@ class ExtractorPowerOrigin( // Should never be more than 0, but handle the possibility val notRemoved = entity.removePower(share) - println("Didn't remove $notRemoved") removeRemaining -= (share - notRemoved) - println("removeRemaining: $removeRemaining") } availableEntities.firstOrNull { it.canRemovePower(removeRemaining) }?.run { @@ -57,9 +53,6 @@ class ExtractorPowerOrigin( override fun getTransferPower(destination: PoweredMultiblockEntity): Int { val destinationCapacity = destination.maxPower - destination.getPower() - println("Room: $destinationCapacity") - println("Available: ${getAvailablePower()}") - println("Transfer limit: ${extractorNode.getTransferPower()}") return minOf(destinationCapacity, transferLimit, getAvailablePower()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt index f0675804b7..00d1077fdd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt @@ -12,23 +12,19 @@ import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead class MoveForward : StepResult { override suspend fun apply(headHolder: HeadHolder) { val branchHead = headHolder.head - println("Trying to move forward") if (branchHead is MultiBranchHead<*>) throw IllegalArgumentException("Multi branches can't be modified!") val currentNode = (branchHead as SingleBranchHead).currentNode tryCast>(currentNode) { - println("was step handler") val next = getNextNode(headHolder.head) ?: return EndBranch().apply(headHolder) - println("next node was $next") branchHead.previousNodes.add(branchHead.currentNode) branchHead.currentNode = next } tryCast>(currentNode) { - println("was destination") finishChain(headHolder.head) } From 4857a122858b1d90f7315711a0376f135894a6f1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 29 Jun 2024 18:08:33 -0500 Subject: [PATCH 077/500] record end rod axis, saving improvements --- .../network/ChunkTransportNetwork.kt | 15 +++++++++-- .../features/transport/node/TransportNode.kt | 8 +++++- .../transport/node/power/EndRodNode.kt | 25 +++++++++++++++++-- .../node/power/PowerExtractorNode.kt | 7 +++--- .../transport/node/power/PowerFlowMeter.kt | 3 ++- .../transport/node/power/PowerInputNode.kt | 12 ++++++++- .../transport/node/power/PowerNodeFactory.kt | 11 ++++---- .../transport/node/power/SolarPanelNode.kt | 7 ++++++ .../ion/server/features/world/IonWorld.kt | 17 +++++++++---- .../miscellaneous/registrations/Components.kt | 3 +++ .../miscellaneous/registrations/Listeners.kt | 2 -- .../persistence/NamespacedKeys.kt | 1 + 12 files changed, 88 insertions(+), 23 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index ff036e34d7..62a001309f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.seconds import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext @@ -67,7 +68,10 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { * @return Whether the data was intact, or up to date **/ fun loadData(): Boolean { - val existing = pdc.get(namespacedKey, PersistentDataType.TAG_CONTAINER) ?: return false + val existing = pdc.get(namespacedKey, PersistentDataType.TAG_CONTAINER) ?: return run { + IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") + false + } val version = pdc.getOrDefault(DATA_VERSION, PersistentDataType.INTEGER, 0) if (version < dataVersion) { @@ -83,10 +87,12 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { }.getOrElse { return false } } + IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} loaded ${nodeData.size} nodes") + nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} loading node into network!") it.printStackTrace() - }.onFailure { return false } } + } } return true } @@ -100,6 +106,11 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { serializedNodes[node] = nodes.values.indexOf(node) to node.serialize(adapterContext, node) } + if (nodes.isNotEmpty()) { + manager.chunk.inner.minecraft.isUnsaved = true + println("Saved ${nodes.size} nodes!") + } + container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.seconds().toTypedArray()) pdc.set(namespacedKey, PersistentDataType.TAG_CONTAINER, container) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 70dd506a65..f8909b45da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -38,10 +38,11 @@ interface TransportNode : PDCSerializable, StepHandler { - constructor(network: ChunkPowerNetwork, origin: Long) : this(network) { + constructor(network: ChunkPowerNetwork, origin: Long, axis: Axis) : this(network) { positions.add(origin) + this.axis = axis } override var isDead: Boolean = false override val positions: MutableSet = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() + var axis by Delegates.notNull() override fun isTransferableTo(node: TransportNode): Boolean { return node !is SourceNode<*> @@ -52,14 +59,28 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } - // Region transfer /* * The extractor node should be allowed to transfer into any regular node. @@ -50,10 +49,12 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, } /* - * Nothing unique with how pathfinding is done, simply move onto a random transferable neighbor + * Nothing unique with how pathfinding is done, simply move onto a random transferable neighbor that isn't a dead end */ override suspend fun getNextNode(head: BranchHead): TransportNode? { - return getTransferableNodes().randomOrNull() + return getTransferableNodes() + .filter { it.getTransferableNodes().isNotEmpty() } + .randomOrNull() } override suspend fun handleHeadStep(head: BranchHead): StepResult { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 092b746ba0..1d57030c5d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -49,7 +50,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { addAverage(TransferredPower(transferred, System.currentTimeMillis())) - network.world.sendMessage(Component.text("Running average transferred is ${calculateAverage()}")) + network.world.sendMessage(Component.text("${toVec3i(position)} ${network.world.name} Running average transferred is ${calculateAverage()}")) } private fun addAverage(average: TransferredPower) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index c9354642f6..8a16e09c94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork @@ -18,6 +19,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates @@ -71,7 +73,15 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest } val remainder = if (origin is ExtractorPowerOrigin) origin.removeOrigin(power) else 0 - destinationMultiblock.addPower(power - remainder) + val toAdd = power - remainder + destinationMultiblock.addPower(toAdd) + + debugAudience.debug(""" + Power endpoint reached! + Origin $origin + $remainder could not be removed + Added $toAdd to $destinationMultiblock + """.trimIndent()) head.previousNodes.forEach { it.onCompleteChain(head, this, power) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 64e4a04886..46893f0de4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes @@ -95,14 +94,14 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory>(mutableListOf()) + val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()) + .values + .filterIsInstance() + .filterTo(mutableListOf()) { it.axis == axis } val finalNode = when (neighbors.size) { // Disconnected - 0 -> EndRodNode(network, position).apply { loadIntoNetwork() } + 0 -> EndRodNode(network, position, data.facing.axis).apply { loadIntoNetwork() } // Consolidate into neighbor 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index d5a4d1bed4..6904fae719 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -194,6 +194,13 @@ class SolarPanelNode( super.buildRelations(position) } + /* + * When the neighbor changes, re-calculate the exit distances + */ + override suspend fun neighborChanged(neighbor: TransportNode) { + traverseField { it.calculateExitDistance() } + } + override suspend fun handleRemoval(position: BlockKey) { isDead = true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index fcac4f0002..34635c2f4b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.configuration.Configuration import net.horizonsend.ion.server.configuration.ConfigurationFiles +import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.machine.AreaShields import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.world.chunk.ChunkRegion @@ -120,7 +121,7 @@ class IonWorld private constructor( // - Mob defenders // - Base shields? - companion object : SLEventListener() { + companion object : IonServerComponent() { private val WORLD_CONFIGURATION_DIRECTORY = ConfigurationFiles.configurationFolder.resolve("worlds").apply { mkdirs() } private val ionWorlds = mutableMapOf() @@ -185,10 +186,16 @@ class IonWorld private constructor( @EventHandler fun onWorldSave(event: WorldSaveEvent) { - for (ionWorld in ionWorlds.values) { - for ((_, chunk) in ionWorld.chunks) { - chunk.save() - } + saveAllChunks(event.world) + } + + override fun onDisable() { + for (world in ionWorlds.keys) saveAllChunks(world) + } + + private fun saveAllChunks(world: World) { + for ((_, chunk) in world.ion.chunks) { + chunk.save() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index c8a6fc3581..758fead94b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -94,6 +94,8 @@ import net.horizonsend.ion.server.features.transport.pipe.Pipes import net.horizonsend.ion.server.features.transport.pipe.filter.Filters import net.horizonsend.ion.server.features.tutorial.Tutorials import net.horizonsend.ion.server.features.waypoint.WaypointManager +import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.features.world.environment.mobs.CustomMobSpawning import net.horizonsend.ion.server.miscellaneous.registrations.legacy.CustomRecipes import net.horizonsend.ion.server.miscellaneous.utils.Notify @@ -107,6 +109,7 @@ val components: List = listOf( Notify, Shuttles, ProxyMessaging, + IonWorld, PlayerXPLevelCache, Levels, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 60cdc2a694..6082d19d84 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -14,7 +14,6 @@ import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager import net.horizonsend.ion.server.features.waypoint.WaypointListeners -import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager import net.horizonsend.ion.server.listener.fixers.BiomeFixer9001 @@ -71,7 +70,6 @@ val listeners: List = listOf( GameplayTweaksListeners(), HeadListener(), HyperspaceBeaconManager, - IonWorld, IonChunk, MiscListeners(), WorldGenerationManager, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 2551878584..10a7c15e52 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -96,6 +96,7 @@ object NamespacedKeys { val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") val NODE_COVERED_POSITIONS = key("node_covered_positions") + val AXIS = key("axis") val SOLAR_CELL_COUNT = key("solar_cell_count") val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") val MULTIBLOCK_DESTINATIONS = key("multiblock_destinations") From f9a0ebbd92f6548053bba8fe54764235dadb9da1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 29 Jun 2024 20:10:39 -0500 Subject: [PATCH 078/500] display entites --- .../client/display/ClientDisplayEntities.kt | 7 +- .../display/container/TextDisplayHandler.kt | 84 +++++++++++++++++++ .../transport/node/power/PowerFlowMeter.kt | 60 ++++++++++++- .../transport/node/power/PowerNodeFactory.kt | 6 +- 4 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt index 4574061543..150aa4a0f9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt @@ -62,7 +62,12 @@ object ClientDisplayEntities : IonServerComponent() { */ fun sendEntityPacket(bukkitPlayer: Player, entity: net.minecraft.world.entity.Entity) { val player = bukkitPlayer.minecraft - val conn = player.connection + + sendEntityPacket(player, entity) + } + + fun sendEntityPacket(player: ServerPlayer, entity: net.minecraft.world.entity.Entity) { + val conn = player.connection conn.send(getAddEntityPacket(entity)) entity.refreshEntityData(player) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt new file mode 100644 index 0000000000..ca5bae07ba --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt @@ -0,0 +1,84 @@ +package net.horizonsend.ion.server.features.client.display.container + +import io.papermc.paper.adventure.PaperAdventure +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData +import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.kyori.adventure.text.Component +import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.Display +import net.minecraft.world.entity.EntityType +import org.bukkit.Bukkit +import org.bukkit.Color +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.craftbukkit.v1_20_R3.CraftServer +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay +import org.bukkit.entity.Display.Billboard +import org.bukkit.entity.Display.Brightness +import org.bukkit.entity.TextDisplay.TextAlignment.CENTER +import org.bukkit.util.Transformation +import org.joml.Quaternionf +import org.joml.Vector3f +import java.util.UUID + +class TextDisplayHandler( + val world: World, + var x: Double, + var y: Double, + var z: Double, + var facing: BlockFace +) { + private val shownPlayers = mutableListOf() + private val nmsEntity: Display.TextDisplay = + CraftTextDisplay( + IonServer.server as CraftServer, + Display.TextDisplay(EntityType.TEXT_DISPLAY, world.minecraft) + ).apply { + billboard = Billboard.FIXED + viewRange = 5.0f + brightness = Brightness(15, 15) + teleportDuration = 0 + backgroundColor = Color.fromARGB(0x00000000) + alignment = CENTER + + transformation = Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector2d(facing.direction.toVector3f()), + Vector3f(1.0f), + Quaternionf() + ) + }.getNMSData(x, y, z) + + fun setText(text: Component) { + nmsEntity.text = PaperAdventure.asVanilla(text) + update() + } + + private fun broadcast(player: ServerPlayer) { + ClientDisplayEntities.sendEntityPacket(player, nmsEntity) + shownPlayers.add(player.uuid) + } + + private fun update(player: ServerPlayer) { + nmsEntity.entityData.refresh(player) + } + + fun update() { + val chunk = world.getChunkAtIfLoaded(x.toInt().shr(4), z.toInt().shr(4)) ?: return + val playerChunk = chunk.minecraft.playerChunk ?: return + + for (player in playerChunk.getPlayers(false)) { + if (shownPlayers.contains(player.uuid)) update(player) else broadcast(player) + } + } + + fun remove() { + for (shownPlayer in shownPlayers) Bukkit.getPlayer(shownPlayer)?.minecraft?.connection?.send( + ClientboundRemoveEntitiesPacket(nmsEntity.id) + ) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 1d57030c5d..85fe1078d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -1,6 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.power +import com.manya.pdc.base.EnumDataType import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth +import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode @@ -12,20 +15,28 @@ import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.kyori.adventure.text.Component +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN +import org.bukkit.block.BlockFace +import org.bukkit.block.BlockFace.NORTH import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + constructor(network: ChunkPowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { this.position = position + this.direction = direction } override var position by Delegates.notNull() override var isDead: Boolean = false override val relationships: MutableSet = ObjectOpenHashSet() + var direction: BlockFace by Delegates.notNull() /* * Should transfer power like any normal node. @@ -50,7 +61,9 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { addAverage(TransferredPower(transferred, System.currentTimeMillis())) - network.world.sendMessage(Component.text("${toVec3i(position)} ${network.world.name} Running average transferred is ${calculateAverage()}")) + + val avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) + displayHandler.setText(text(avg, GREEN)) } private fun addAverage(average: TransferredPower) { @@ -77,12 +90,51 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step return sum / timeDiff } + private lateinit var displayHandler: TextDisplayHandler + + private fun setupDisplayEntity() { + // 95% of the way to the edge of the block once added to the center of the block, to avoid z fighting + val offset = direction.direction.multiply(0.45) + + val facingBlock = getRelative(position, direction) + + val x = getX(facingBlock).toDouble() + 0.5 - offset.x + val y = getY(facingBlock).toDouble() + 0.5 + val z = getZ(facingBlock).toDouble() + 0.5 - offset.z + + displayHandler = TextDisplayHandler( + network.world, + x, + y, + z, + direction + ) + } + + override fun loadIntoNetwork() { + setupDisplayEntity() + + super.loadIntoNetwork() + } + + override suspend fun onPlace(position: BlockKey) { + setupDisplayEntity() + + super.onPlace(position) + } + + override suspend fun handleRemoval(position: BlockKey) { + if (::displayHandler.isInitialized) displayHandler.remove() + } + override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(BlockFace::class.java), direction) } override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + direction = persistentDataContainer.getOrDefault(NamespacedKeys.AXIS, EnumDataType(BlockFace::class.java), NORTH) } private data class TransferredPower(val transferred: Int, val time: Long) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 46893f0de4..1dd4a2ac3e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -53,7 +53,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory addInput(key) - snapshot.type == Material.OBSERVER -> addFlowMeter(key) + snapshot.type == Material.OBSERVER -> addFlowMeter(snapshot.data as Directional, key) // Merge node behavior snapshot.type == Material.IRON_BLOCK -> addMergeNode(key) @@ -127,8 +127,8 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory Date: Wed, 10 Jul 2024 16:06:29 -0500 Subject: [PATCH 079/500] power multiblock display --- .../display/container/TextDisplayHandler.kt | 5 +-- .../multiblock/ChunkMultiblockManager.kt | 4 ++- .../multiblock/entity/MultiblockEntity.kt | 3 ++ .../{ => power}/PoweredMultiblockEntity.kt | 17 ++------- ...impleTextDisplayPoweredMultiblockEntity.kt | 35 +++++++++++++++++++ .../powerbank/new/NewPowerBankMultiblock.kt | 12 +++++-- .../transport/node/power/PowerFlowMeter.kt | 9 ++--- .../transport/node/power/PowerInputNode.kt | 2 +- .../step/origin/ExtractorPowerOrigin.kt | 2 +- .../transport/step/origin/PowerOrigin.kt | 2 +- .../transport/step/origin/SolarPowerOrigin.kt | 2 +- 11 files changed, 64 insertions(+), 29 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/{ => power}/PoweredMultiblockEntity.kt (77%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt index ca5bae07ba..ed4b50940e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt @@ -30,6 +30,7 @@ class TextDisplayHandler( var x: Double, var y: Double, var z: Double, + val scale: Float, var facing: BlockFace ) { private val shownPlayers = mutableListOf() @@ -47,8 +48,8 @@ class TextDisplayHandler( transformation = Transformation( Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(facing.direction.toVector3f()), - Vector3f(1.0f), + ClientDisplayEntities.rotateToFaceVector2d(this@TextDisplayHandler.facing.direction.toVector3f()), + Vector3f(scale), Quaternionf() ) }.getNMSData(x, y, z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index ca3f9c7da7..d865e0f11e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -4,8 +4,8 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES @@ -177,6 +177,8 @@ class ChunkMultiblockManager(val chunk: IonChunk) { syncTickingMultiblockEntities.remove(key) asyncTickingMultiblockEntities.remove(key) + entity?.handleRemoval() + return entity } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 2559f51703..03b45cf666 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -51,6 +51,9 @@ abstract class MultiblockEntity( val locationKey = toBlockKey(x, y, z) + /** Logic to be run upon the removal of this entity */ + open fun handleRemoval() {} + /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt similarity index 77% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index d2acecd254..d298d86f48 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,13 +1,9 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type +package net.horizonsend.ion.server.features.multiblock.entity.type.power import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.front import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor @@ -24,7 +20,6 @@ interface PoweredMultiblockEntity { powerUnsafe = correctedPower - //TODO better solution updatePowerVisually() } @@ -80,15 +75,7 @@ interface PoweredMultiblockEntity { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, powerUnsafe) } - fun updatePowerVisually() { - //TODO replace this - require(this is MultiblockEntity) - Tasks.sync { - val sign = getSign() ?: throw NullPointerException("Tried to update visual on a multiblock without an intact sign : ${world.name} ${toVec3i(position)}") - sign.front().line(2, formatPower()) - sign.update() - } - } + fun updatePowerVisually() fun formatPower(): Component = ofChildren(prefixComponent, text(powerUnsafe, GREEN)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt new file mode 100644 index 0000000000..f396015682 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt @@ -0,0 +1,35 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.power + +import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i + +/** + * Interface providing a simple implementation of a visual display via text display entities. + **/ +interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity { + val powerDisplay: TextDisplayHandler + + override fun updatePowerVisually() { + powerDisplay.setText(formatPower()) + } + + fun createTextDisplayHandler(): TextDisplayHandler { + require(this is MultiblockEntity) + + val signDirection = facing.oppositeFace + val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) + + // 70% of the way through the block + val offset = signDirection.direction.multiply(0.39) + + return TextDisplayHandler( + world, + signLoc.x.toDouble() + 0.5 - offset.x, + signLoc.y.toDouble() + 0.4, + signLoc.z.toDouble() + 0.5 - offset.z, + 0.5f, + signDirection + ) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 0fd7e3789d..d99fa74558 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -1,10 +1,11 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock @@ -102,14 +103,19 @@ abstract class NewPowerBankMultiblock signDirection: BlockFace, override val maxPower: Int, override var powerUnsafe: Int = 0 - ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { + override val powerDisplay: TextDisplayHandler = createTextDisplayHandler() + + override fun handleRemoval() { + powerDisplay.remove() + } override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) } override fun toString(): String { - return "POWER BANK TIER: $multiblock! ${world.name} $x $y $z Power: ${getPower()}!!!" + return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $facing" } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 85fe1078d4..34bf0daa19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -60,17 +60,17 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step private val averages = mutableListOf() override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { - addAverage(TransferredPower(transferred, System.currentTimeMillis())) + addTransferred(TransferredPower(transferred, System.currentTimeMillis())) val avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) displayHandler.setText(text(avg, GREEN)) } - private fun addAverage(average: TransferredPower) { + private fun addTransferred(transferredSnapshot: TransferredPower) { val currentSize = averages.size if (currentSize < STORED_AVERAGES) { - averages.add(average) + averages.add(transferredSnapshot) return } @@ -79,7 +79,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step averages[index + 1] = averages[index] } - averages[0] = average + averages[0] = transferredSnapshot } private fun calculateAverage(): Double { @@ -107,6 +107,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step x, y, z, + 1.0f, direction ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 8a16e09c94..bc5cfa584c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt index b6cbec23d2..dc7a3ffb20 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.step.origin import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt index aef7731e2c..a3c967d80a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.step.origin -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity interface PowerOrigin { fun getTransferPower(destination: PoweredMultiblockEntity): Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt index 95d2da7f75..9a4e06d410 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.step.origin -import net.horizonsend.ion.server.features.multiblock.entity.type.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode From 88c9d2977c8cab12c72d743fd3a26497c3b56c9f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 01:34:56 -0500 Subject: [PATCH 080/500] saving / loading reliability improvements, cleanup --- .../net/horizonsend/ion/server/IonServer.kt | 1 + .../transport/ChunkTransportManager.kt | 3 +- .../transport/network/ChunkPowerNetwork.kt | 6 +- .../network/ChunkTransportNetwork.kt | 141 ++++++++++-------- .../ion/server/features/world/IonWorld.kt | 25 +++- .../features/world/chunk/ChunkRegion.kt | 15 +- .../server/features/world/chunk/IonChunk.kt | 16 +- .../persistence/NamespacedKeys.kt | 4 +- 8 files changed, 123 insertions(+), 88 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt index b6828ae1a7..1b91a532d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt @@ -151,6 +151,7 @@ object IonServer : JavaPlugin() { for (component in components.asReversed()) try { component.onDisable() + slF4JLogger.info("Disabled ${component.javaClass.simpleName}") } catch (e: Exception) { slF4JLogger.error("There was an error shutting down ${component.javaClass.simpleName}! ${e.message}") e.printStackTrace() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index d3483d94a3..a69039c607 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -18,8 +18,7 @@ class ChunkTransportManager( // val gasGrid = ChunkPowerNetwork(this) // TODO fun setup() { - powerNetwork.build() - powerNetwork.finalizeNetwork() + powerNetwork.loadNetwork() // TODO // TODO } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index ee28aec61f..54a4df92ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -50,7 +50,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( tickExtractors() } - override suspend fun clearData() { + override fun clearData() { nodes.clear() solarPanels.clear() extractors.clear() @@ -68,8 +68,4 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( it.value.buildRelations(getRelative(new.locationKey, it.key)) } } - - companion object { - const val POWER_EXTRACTOR_STEP = 1000 - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index 62a001309f..73c9057abf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -18,11 +18,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.seconds import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER import java.util.concurrent.ConcurrentHashMap abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { @@ -32,17 +32,21 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { val world get() = manager.chunk.world - val pdc get() = manager.chunk.inner.persistentDataContainer + protected val chunkPDC get() = manager.chunk.inner.persistentDataContainer + protected val networkPDC get() = chunkPDC.get( + namespacedKey, + TAG_CONTAINER + ) ?: run { + IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") + + chunkPDC.adapterContext.newPersistentDataContainer() + } protected abstract val namespacedKey: NamespacedKey protected abstract val type: NetworkType abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int - fun finalizeNetwork() { - ready = true - } - open fun processBlockRemoval(key: Long) { manager.scope.launch { withTransportDisabled { val previousNode = nodes[key] ?: return@withTransportDisabled @@ -62,17 +66,62 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { withTransportDisabled { nodeFactory.create(key, block) } } + /** + * Save additional metadata into the network PDC + **/ + open fun saveAdditional(pdc: PersistentDataContainer) {} + + suspend fun tickIfReady() { if (ready) tick() } + + abstract suspend fun tick() + + abstract fun clearData() + + /** + * Logic for when the holding chunk is unloaded + **/ + fun onUnload() { + // Break cross chunk relations + breakAllRelations() + + save(manager.chunk.inner.persistentDataContainer.adapterContext) + } + + /** + * Builds the transportNetwork + * + * Existing data will be loaded from the chunk's persistent data container, relations between nodes will be built, and any finalization will be performed + **/ + fun loadNetwork() { + val adapterContext = chunkPDC.adapterContext + + // Load data sync + val good = loadData() + + manager.scope.launch { + // Handle cases of data corruption + if (!good) { + clearData() + collectAllNodes().join() + + // Save rebuilt data + save(adapterContext) + } + + buildRelations() + finalizeNodes() + + ready = true + } + } + /** * Load stored node data from the chunk * * @return Whether the data was intact, or up to date **/ fun loadData(): Boolean { - val existing = pdc.get(namespacedKey, PersistentDataType.TAG_CONTAINER) ?: return run { - IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") - false - } - val version = pdc.getOrDefault(DATA_VERSION, PersistentDataType.INTEGER, 0) + val version = networkPDC.getOrDefault(DATA_VERSION, PersistentDataType.INTEGER, 0) if (version < dataVersion) { IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained outdated data! It will be rebuilt") @@ -80,18 +129,19 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { } // Deserialize once - val nodeData = existing.getOrDefault(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).mapNotNull { + val nodeData = networkPDC.getOrDefault(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).map { runCatching { TransportNode.load(it, this) }.onFailure { IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained corrupted data! It will be rebuilt") it.printStackTrace() - }.getOrElse { return false } + }.getOrElse { + return false + } } - IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} loaded ${nodeData.size} nodes") - nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} loading node into network!") it.printStackTrace() + return false } } return true @@ -100,63 +150,22 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { fun save(adapterContext: PersistentDataAdapterContext) { val container = adapterContext.newPersistentDataContainer() - val serializedNodes: MutableMap> = mutableMapOf() + val serializedNodes: MutableMap = mutableMapOf() - nodes.forEach { (_, node) -> - serializedNodes[node] = nodes.values.indexOf(node) to node.serialize(adapterContext, node) + nodes.values.distinct().forEach { node -> + serializedNodes[node] = node.serialize(adapterContext, node) } - if (nodes.isNotEmpty()) { + if (serializedNodes.isNotEmpty()) { manager.chunk.inner.minecraft.isUnsaved = true - println("Saved ${nodes.size} nodes!") } - container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.seconds().toTypedArray()) - - pdc.set(namespacedKey, PersistentDataType.TAG_CONTAINER, container) - pdc.set(DATA_VERSION, PersistentDataType.INTEGER, dataVersion) - - saveAdditional(pdc) - } - - open fun saveAdditional(pdc: PersistentDataContainer) {} - - suspend fun tickIfReady() { if (ready) tick() } - - /** - * - **/ - abstract suspend fun tick() - - abstract suspend fun clearData() - - /** - * Logic for when the holding chunk is unloaded - **/ - fun onUnload() { - // Break cross chunk relations - breakAllRelations() - - save(manager.chunk.inner.persistentDataContainer.adapterContext) - } - - /** - * Builds the transportNetwork - * - * Existing data will be loaded from the chunk's persistent data container, relations between nodes will be built, and any finalization will be performed - **/ - fun build() = manager.scope.launch { - if (!loadData()) { - clearData() - collectAllNodes().join() - } - - // Save rebuilt data - save(manager.chunk.inner.persistentDataContainer.adapterContext) + container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.toTypedArray()) + container.set(DATA_VERSION, PersistentDataType.INTEGER, dataVersion) + saveAdditional(container) - buildRelations() - finalizeNodes() - finalizeNetwork() + // Save the network PDC + chunkPDC.set(namespacedKey, TAG_CONTAINER, container) } /** @@ -174,7 +183,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { * * Iterate the section for possible nodes, handle creation **/ - suspend fun collectSectionNodes(sectionY: Int) { + private suspend fun collectSectionNodes(sectionY: Int) { val originX = manager.chunk.originX val originY = sectionY.shl(4) - manager.chunk.inner.world.minHeight val originZ = manager.chunk.originZ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 34635c2f4b..0380990111 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -39,7 +39,7 @@ class IonWorld private constructor( **/ private val chunks: ConcurrentHashMap = ConcurrentHashMap() val regionPositions: ConcurrentHashMap = ConcurrentHashMap() - val chunkRegions: MutableSet = ObjectOpenHashSet() + val chunkRegions: MutableSet = ObjectOpenHashSet() /** * Gets the IonChunk at the specified coordinates if it is loaded @@ -147,7 +147,14 @@ class IonWorld private constructor( fun unregisterAll() { mainThreadCheck() - ionWorlds.clear() + val iterator = ionWorlds.iterator() + + while (iterator.hasNext()) { + val (_, ionWorld) = iterator.next() + + saveAllChunks(ionWorld) + iterator.remove() + } } @Deprecated("Event Listener", level = ERROR) @@ -163,7 +170,11 @@ class IonWorld private constructor( fun onWorldUnloadEvent(event: WorldUnloadEvent) { mainThreadCheck() - ionWorlds.remove(event.world) + val bukkitWorld = event.world + val ionWorld = ionWorlds[bukkitWorld]!! + + saveAllChunks(ionWorld) + ionWorlds.remove(bukkitWorld) } @Deprecated("Event Listener", level = ERROR) @@ -186,15 +197,15 @@ class IonWorld private constructor( @EventHandler fun onWorldSave(event: WorldSaveEvent) { - saveAllChunks(event.world) + saveAllChunks(event.world.ion) } override fun onDisable() { - for (world in ionWorlds.keys) saveAllChunks(world) + for (world in ionWorlds.values) saveAllChunks(world) } - private fun saveAllChunks(world: World) { - for ((_, chunk) in world.ion.chunks) { + private fun saveAllChunks(world: IonWorld) { + for ((_, chunk) in world.chunks) { chunk.save() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index 9be87bb941..e864622c6c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.world.chunk -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.asCoroutineDispatcher @@ -9,13 +8,15 @@ import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import org.bukkit.Chunk -import java.util.concurrent.ForkJoinPool +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Executors class ChunkRegion(val world: IonWorld) { - val chunks = Long2ObjectOpenHashMap() + val chunks = ConcurrentHashMap() - val size get() = chunks.long2ObjectEntrySet().size + val size get() = chunks.values.size val tickChunkTransport = IntervalExecutor(4) { @@ -47,10 +48,14 @@ class ChunkRegion(val world: IonWorld) { fun launch(block: suspend CoroutineScope.() -> Unit) = scope.launch { block.invoke(this) } companion object { - val scope = CoroutineScope(ForkJoinPool(64).asCoroutineDispatcher() + SupervisorJob()) + val scope = CoroutineScope(Executors.newCachedThreadPool(Tasks.namedThreadFactory("chunk-async-worker")).asCoroutineDispatcher() + SupervisorJob()) const val MAX_SIZE: Int = 50 fun loadChunk(chunk: Chunk) { + if (chunk.world.ion.getChunk(chunk.chunkKey) != null) { + return + } + val region: ChunkRegion = findRegion(chunk) val ionChunk = IonChunk.registerChunk(chunk, region) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 3f0424537a..e9b5683986 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.world.chunk +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -18,6 +19,7 @@ import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.INTEGER +import java.util.concurrent.ConcurrentHashMap class IonChunk( val inner: Chunk, @@ -88,9 +90,21 @@ class IonChunk( } companion object : SLEventListener() { + private val loadingTasks = ConcurrentHashMap.newKeySet() + @EventHandler fun onChunkLoad(event: ChunkLoadEvent) { + val key = event.chunk.chunkKey + + if (loadingTasks.contains(key)) { + IonServer.slF4JLogger.warn("Detected double chuck load for ${event.chunk.x} ${event.chunk.z} in ${event.chunk.world.name}") + return + } + + loadingTasks.add(key) + ChunkRegion.loadChunk(event.chunk) + loadingTasks.remove(key) } @EventHandler @@ -160,6 +174,6 @@ class IonChunk( fun markUnsaved() { inner.minecraft.isUnsaved = true } override fun toString(): String { - return "IonChunk[$x, $z]" + return "IonChunk[$x, $z @ ${world.name}]" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 10a7c15e52..c2355f7fb0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -86,7 +86,6 @@ object NamespacedKeys { val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") val STORED_MULTIBLOCK_ENTITIES_OLD = key("stored_multiblock_entities_old") - val EXTRACTOR_DATA = key("extractor_data") val RESOURCE_CAPACITY_MAX = key("resource_capacity_max") val RESOURCE_CAPACITY_MIN = key("resource_capacity_min") @@ -100,10 +99,11 @@ object NamespacedKeys { val SOLAR_CELL_COUNT = key("solar_cell_count") val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") val MULTIBLOCK_DESTINATIONS = key("multiblock_destinations") + val NODE_TYPE = key("node_type") val NODE_ORIGIN = key("node_origin") - val NODES = key("chunk_power_nodes") + val NODES = key("chunk_nodes") fun key(key: String) = NamespacedKey(IonServer, key) From db086212a6ba2adc01bc636c10e2777ff02fa860 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 01:49:54 -0500 Subject: [PATCH 081/500] fix solars not recalculating exit distance upon building a relation --- .../transport/network/ChunkTransportNetwork.kt | 3 ++- .../features/transport/node/NodeRelationship.kt | 2 +- .../features/transport/node/TransportNode.kt | 9 +++++---- .../transport/node/power/SolarPanelNode.kt | 16 ++++++++++------ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index 73c9057abf..9940b8cac8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.network import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync @@ -220,7 +221,7 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { open fun finalizeNodes() {} fun breakAllRelations() { - nodes.values.forEach { it.clearRelations() } + runBlocking { nodes.values.forEach { it.clearRelations() } } } fun getNode(x: Int, y: Int, z: Int): TransportNode? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index fc5828625a..a172ee0ad6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -19,7 +19,7 @@ data class NodeRelationship( /** * Break the relation between the two nodes **/ - fun breakUp() { + suspend fun breakUp() { sideOne.node.removeRelationship(sideTwo.node) sideTwo.node.removeRelationship(sideOne.node) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index f8909b45da..7127a3541d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -27,7 +27,7 @@ interface TransportNode : PDCSerializable() if (solars.isEmpty()) { exitDistance = -1 + println("No exit available") return } @@ -189,9 +192,10 @@ class SolarPanelNode( // If relations have changed, update the exit distances of the whole field override suspend fun buildRelations(position: BlockKey) { - traverseField { it.calculateExitDistance() } - super.buildRelations(position) + + // Calculate exit distance after relations have been built + traverseField { it.calculateExitDistance() } } /* @@ -296,10 +300,10 @@ class SolarPanelNode( suspend fun matchesSolarPanelStructure(world: World, key: BlockKey): Boolean { if (getBlockSnapshotAsync(world, key)?.type != Material.CRAFTING_TABLE) return false - val diamond = getRelative(key, BlockFace.UP) + val diamond = getRelative(key, UP) if (getBlockSnapshotAsync(world, diamond)?.type != Material.DIAMOND_BLOCK) return false - val cell = getRelative(diamond, BlockFace.UP) + val cell = getRelative(diamond, UP) return getBlockSnapshotAsync(world, cell)?.type == Material.DAYLIGHT_DETECTOR } From 8d4356ff89e4312cb1c3ed2f2fdb300bc9dd0f60 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 01:50:10 -0500 Subject: [PATCH 082/500] fix power flow meter not removing properly --- .../ion/server/features/transport/node/power/PowerFlowMeter.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 34bf0daa19..678b23ccf2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -126,6 +126,8 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step override suspend fun handleRemoval(position: BlockKey) { if (::displayHandler.isInitialized) displayHandler.remove() + + super.handleRemoval(position) } override fun storeData(persistentDataContainer: PersistentDataContainer) { From 76128ae2904cfd65329928cf58e49f1f9d47b9ee Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 02:01:47 -0500 Subject: [PATCH 083/500] forgot printlns --- .../server/features/transport/node/power/SolarPanelNode.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index a6805dcbc1..6d8abf38ee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -105,19 +105,15 @@ class SolarPanelNode( private fun calculateExitDistance() { val neighbors = getTransferableNodes() - println("Solar $this calculating exit distance") - // Transferable node provides an exit if (neighbors.any { it !is SolarPanelNode }) { exitDistance = 0 - println("Exit available") return } val solars = neighbors.filterIsInstance() if (solars.isEmpty()) { exitDistance = -1 - println("No exit available") return } From efaabe7f80a4cfd41e024ef5b2e91e27c0192242 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 14:10:01 -0500 Subject: [PATCH 084/500] record node relationship directions --- .../transport/node/NodeRelationship.kt | 11 +++--- .../features/transport/node/NodeType.kt | 4 +-- .../features/transport/node/TransportNode.kt | 5 +-- .../{MergeNode.kt => DirectionalNode.kt} | 14 ++++++-- .../transport/node/power/EndRodNode.kt | 2 +- .../node/power/InvertedDirectionalNode.kt | 4 +++ .../node/power/PowerExtractorNode.kt | 2 +- .../transport/node/power/PowerNodeFactory.kt | 34 ++++++++++++------- .../transport/node/power/SolarPanelNode.kt | 6 ++-- .../transport/node/power/SpongeNode.kt | 10 +++++- .../features/transport/node/type/MultiNode.kt | 2 +- .../transport/node/type/SingleNode.kt | 2 +- .../persistence/NamespacedKeys.kt | 6 ++-- 13 files changed, 68 insertions(+), 34 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/{MergeNode.kt => DirectionalNode.kt} (77%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index a172ee0ad6..7e39a48d28 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.transport.node +import org.bukkit.block.BlockFace + /** * This class represents a relationship between two nodes * The information contains whether they may transfer to / from each other, from each side @@ -13,8 +15,9 @@ data class NodeRelationship( * * @param node The node on this side of the relationship * @param transferAllowed Whether this node is allowed to transfer to the other side + * @param nodeTwoOffset The BlockFace which this side can be found from the other side **/ - data class RelationSide(val node: TransportNode, val transferAllowed: Boolean) + data class RelationSide(val node: TransportNode, val transferAllowed: Boolean, val offset: BlockFace) /** * Break the relation between the two nodes @@ -25,15 +28,15 @@ data class NodeRelationship( } companion object { - fun create(nodeOne: TransportNode, nodeTwo: TransportNode) { + fun create(nodeOne: TransportNode, nodeTwo: TransportNode, nodeTwoOffset: BlockFace) { val canTransferTo = nodeOne.isTransferableTo(nodeTwo) val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) // Do not add the relationship if neither side can transfer if (!canTransferFrom && !canTransferTo) return - nodeOne.relationships += NodeRelationship(RelationSide(nodeOne, canTransferTo), RelationSide(nodeTwo, canTransferFrom)) - nodeTwo.relationships += NodeRelationship(RelationSide(nodeTwo, canTransferFrom), RelationSide(nodeOne, canTransferTo)) + nodeOne.relationships += NodeRelationship(RelationSide(nodeOne, canTransferTo, BlockFace.SELF), RelationSide(nodeTwo, canTransferFrom, nodeTwoOffset)) + nodeTwo.relationships += NodeRelationship(RelationSide(nodeTwo, canTransferFrom, BlockFace.SELF), RelationSide(nodeOne, canTransferTo, nodeTwoOffset.oppositeFace)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 44ad89ab3a..fc6436182f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -2,8 +2,8 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.power.DirectionalNode import net.horizonsend.ion.server.features.transport.node.power.EndRodNode -import net.horizonsend.ion.server.features.transport.node.power.MergeNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode @@ -18,7 +18,7 @@ enum class NodeType(val clazz: Class) { POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), POWER_FLOW_METER(PowerFlowMeter::class.java), - MERGE_NODE(MergeNode::class.java), + MERGE_NODE(DirectionalNode::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 7127a3541d..20de67b4b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -38,11 +39,11 @@ interface TransportNode : PDCSerializable { +class DirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() + private var variant: Material by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + constructor(network: ChunkPowerNetwork, position: BlockKey, variant: Material) : this(network) { this.position = position + this.variant = variant } override fun isTransferableTo(node: TransportNode): Boolean { @@ -40,9 +44,15 @@ class MergeNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandl override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + persistentDataContainer.set(NamespacedKeys.NODE_VARIANT, materialDataType, variant) } override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + variant = persistentDataContainer.get(NamespacedKeys.NODE_VARIANT, materialDataType)!! + } + + companion object { + val materialDataType = EnumDataType(Material::class.java) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 1527b73da3..4241160a12 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -66,7 +66,7 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode addSponge(key) // Extract power from storage - snapshot.type == Material.CRAFTING_TABLE -> if (matchesSolarPanelStructure(network.world, key)) { - addSolarPanel(key) - } else { - addExtractor(key) + snapshot.type == Material.CRAFTING_TABLE -> { + if (matchesSolarPanelStructure(network.world, key)) { + addSolarPanel(key) + } else { + addExtractor(key) + } } // Check for extractor beneath snapshot.type == Material.DIAMOND_BLOCK -> { val extractorKey = getRelative(key, DOWN, 1) - network.nodes.remove(extractorKey) + if (matchesSolarPanelStructure(network.world, extractorKey)) { + network.nodes.remove(extractorKey) addSolarPanel(extractorKey) } } snapshot.type == Material.DAYLIGHT_DETECTOR -> { val extractorKey = getRelative(key, DOWN, 2) - network.nodes.remove(extractorKey) + if (matchesSolarPanelStructure(network.world, extractorKey)) { + network.nodes.remove(extractorKey) addSolarPanel(extractorKey) } } // Add power to storage snapshot.type == Material.NOTE_BLOCK -> addInput(key) + + // Power flow meter snapshot.type == Material.OBSERVER -> addFlowMeter(snapshot.data as Directional, key) // Merge node behavior - snapshot.type == Material.IRON_BLOCK -> addMergeNode(key) - snapshot.type == Material.REDSTONE_BLOCK -> addMergeNode(key) + snapshot.type == Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) + snapshot.type == Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) // Split power evenly // block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) @@ -65,8 +71,6 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory GateNode(this, x, y, z) - // Power flow meter - else -> return } } @@ -178,9 +182,15 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory, Z: MultiNode> : Transport if (this == neighborNode) continue - addRelationship(neighborNode) + addRelationship(neighborNode, offset) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 05d22188b5..67631959fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -23,7 +23,7 @@ interface SingleNode : TransportNode { if (this == neighborNode) return // Add a relationship, if one should be added - addRelationship(neighborNode) + addRelationship(neighborNode, offset) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index c2355f7fb0..f6a01d4d2f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -93,15 +93,13 @@ object NamespacedKeys { val PROCESSING_PROGRESS = key("processing_progress") - val TRANSFERABLE_NEIGHBORS = key("transferable_neighbors") val NODE_COVERED_POSITIONS = key("node_covered_positions") val AXIS = key("axis") - val SOLAR_CELL_COUNT = key("solar_cell_count") val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") - val MULTIBLOCK_DESTINATIONS = key("multiblock_destinations") val NODE_TYPE = key("node_type") - val NODE_ORIGIN = key("node_origin") + + val NODE_VARIANT = key("node_variant") val NODES = key("chunk_nodes") From 656dde40d173bcc056a0fdecf32d97ecbcb37073 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 14:43:18 -0500 Subject: [PATCH 085/500] record direction when stepping --- .../features/transport/node/TransportNode.kt | 4 ++-- .../transport/node/power/DirectionalNode.kt | 10 +++++---- .../transport/node/power/EndRodNode.kt | 9 ++++---- .../node/power/PowerExtractorNode.kt | 10 +++++---- .../transport/node/power/PowerFlowMeter.kt | 7 ++++--- .../transport/node/power/SolarPanelNode.kt | 21 ++++++++++++------- .../transport/node/power/SpongeNode.kt | 9 ++++---- .../transport/node/type/StepHandler.kt | 7 ++++--- .../transport/step/head/SingleBranchHead.kt | 8 +++++++ .../step/head/power/SinglePowerBranchHead.kt | 5 +++-- .../transport/step/result/MoveForward.kt | 6 ++++-- 11 files changed, 60 insertions(+), 36 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 20de67b4b1..a873e367e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -61,10 +61,10 @@ interface TransportNode : PDCSerializable = relationships.filter { + fun getTransferableNodes(): Collection> = relationships.filter { // That this node can transfer to the other it.sideOne.transferAllowed && !it.sideTwo.node.isDead - }.map { it.sideTwo.node } + }.map { it.sideTwo.node to it.sideOne.offset } /** * Store additional required data in the serialized container diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt index f5ff3ced1b..69737ebe55 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt @@ -8,12 +8,13 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates @@ -33,11 +34,12 @@ class DirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, Ste return node !is SourceNode<*> } - override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it) } + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() - override suspend fun handleHeadStep(head: BranchHead): StepResult { + + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 4241160a12..392bcaece3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -18,6 +18,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Axis +import org.bukkit.block.BlockFace import org.bukkit.block.data.Directional import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -38,13 +39,13 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode } - override suspend fun handleHeadStep(head: BranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } - override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it) } + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } .firstOrNull() override suspend fun rebuildNode(position: BlockKey) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 68e699add8..63b4d1fa64 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin @@ -18,6 +18,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt @@ -51,13 +52,13 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, /* * Nothing unique with how pathfinding is done, simply move onto a random transferable neighbor that isn't a dead end */ - override suspend fun getNextNode(head: BranchHead): TransportNode? { + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { return getTransferableNodes() - .filter { it.getTransferableNodes().isNotEmpty() } + .filter { it.first.getTransferableNodes().isNotEmpty() } .randomOrNull() } - override suspend fun handleHeadStep(head: BranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { return MoveForward() } @@ -73,6 +74,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, ) { SinglePowerBranchHead( holder = this, + lastDirection = BlockFace.SELF, currentNode = this@PowerExtractorNode, share = 1.0, ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 678b23ccf2..cbfcf5c618 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -47,13 +48,13 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step return node !is SourceNode<*> } - override suspend fun handleHeadStep(head: BranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } - override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it) } + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() private val STORED_AVERAGES = 20 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index a996b644b4..6cd14571dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead import net.horizonsend.ion.server.features.transport.step.origin.SolarPowerOrigin import net.horizonsend.ion.server.features.transport.step.result.MoveForward @@ -26,7 +26,9 @@ import net.minecraft.world.level.LightLayer import org.bukkit.GameRule import org.bukkit.Material import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN +import org.bukkit.block.BlockFace.SELF import org.bukkit.block.BlockFace.UP import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LONG_ARRAY @@ -69,13 +71,14 @@ class SolarPanelNode( ) { SinglePowerBranchHead( holder = this, + lastDirection = SELF, currentNode = this@SolarPanelNode, share = 1.0, ) } } - override suspend fun handleHeadStep(head: BranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } @@ -88,14 +91,16 @@ class SolarPanelNode( **/ private var exitDistance: Int = 0 - override suspend fun getNextNode(head: BranchHead): TransportNode? { + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { val neighbors = getTransferableNodes() - return neighbors.shuffled().firstOrNull { it !is SolarPanelNode } ?: + return neighbors.shuffled().firstOrNull { it.first !is SolarPanelNode } ?: neighbors - .filterIsInstance() - .filter { it.exitDistance < this.exitDistance } // Make sure it can't move further from an exit + .filter { + val node = it.first + node is SolarPanelNode && node.exitDistance < this.exitDistance + } // Make sure it can't move further from an exit .shuffled() // Make sure the lowest priority, if multiple is random every time - .minByOrNull { it.exitDistance } + .minByOrNull { (it.first as SolarPanelNode).exitDistance } } /** @@ -106,7 +111,7 @@ class SolarPanelNode( val neighbors = getTransferableNodes() // Transferable node provides an exit - if (neighbors.any { it !is SolarPanelNode }) { + if (neighbors.any { it.first !is SolarPanelNode }) { exitDistance = 0 return } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index e7ec61a136..907fcebd18 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -8,11 +8,12 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -56,13 +57,13 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } - override suspend fun getNextNode(head: BranchHead): TransportNode? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it) } + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } .firstOrNull() // override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt index 6b0b238bbf..2f234b479b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt @@ -2,8 +2,9 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.head.BranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.result.StepResult +import org.bukkit.block.BlockFace interface StepHandler { /** @@ -12,7 +13,7 @@ interface StepHandler { * This may create a new step for a single node, spawn off multiple steps, or more * Each node defines how it is stepped. **/ - suspend fun handleHeadStep(head: BranchHead): StepResult + suspend fun handleHeadStep(head: SingleBranchHead): StepResult - suspend fun getNextNode(head: BranchHead): TransportNode? + suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt index 9b40d382e1..030d60f769 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt @@ -2,7 +2,15 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode +import org.bukkit.block.BlockFace +/** + * Can either branch off of a MultiBranch or exist alone + **/ interface SingleBranchHead : BranchHead { + /** The last offset this branch moved */ + var lastDirection: BlockFace + + /** The current location of the tip of the branch */ var currentNode: TransportNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index 3166544f58..444ac9b393 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -7,9 +7,9 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import org.bukkit.block.BlockFace /** * Transferred power down a single path. @@ -18,6 +18,7 @@ import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead **/ class SinglePowerBranchHead( override val holder: Step, + override var lastDirection: BlockFace, override var currentNode: TransportNode, override val share: Double, override val previousNodes: MutableSet = mutableSetOf() @@ -39,7 +40,7 @@ class SinglePowerBranchHead( // All other nodes handle steps transferring in / out node as StepHandler - val result = node.handleHeadStep(this as BranchHead) + val result = node.handleHeadStep(this as SingleBranchHead) result.apply(holder as HeadHolder) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt index 00d1077fdd..46a9e08a7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead /** A result which moves the head of the branch forward, using the current node's pathfinding */ -class MoveForward : StepResult { +class MoveForward() : StepResult { override suspend fun apply(headHolder: HeadHolder) { val branchHead = headHolder.head @@ -17,11 +17,13 @@ class MoveForward : StepResult { val currentNode = (branchHead as SingleBranchHead).currentNode + // If the next node is a step handler, tryCast>(currentNode) { - val next = getNextNode(headHolder.head) ?: return EndBranch().apply(headHolder) + val (next, offset) = this.getNextNode(branchHead, branchHead.lastDirection) ?: return EndBranch().apply(headHolder) branchHead.previousNodes.add(branchHead.currentNode) branchHead.currentNode = next + branchHead.lastDirection = offset } tryCast>(currentNode) { From a12749233af202ab02b1f62fe76bb8f8328047aa Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 19:55:27 -0500 Subject: [PATCH 086/500] improve power flow meter UI --- .../transport/node/power/PowerFlowMeter.kt | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index cbfcf5c618..ad40b2fcf5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -3,6 +3,8 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth +import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship @@ -20,8 +22,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN +import net.kyori.adventure.text.format.NamedTextColor.YELLOW import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.NORTH import org.bukkit.persistence.PersistentDataContainer @@ -63,8 +68,17 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { addTransferred(TransferredPower(transferred, System.currentTimeMillis())) + displayHandler.setText(formatPower()) + } + + companion object { + val firstLine = text("E: ", YELLOW) + val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Second", GREEN)) + } + + private fun formatPower(): Component { val avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) - displayHandler.setText(text(avg, GREEN)) + return ofChildren(firstLine, text(avg, GREEN), secondLine) } private fun addTransferred(transferredSnapshot: TransferredPower) { @@ -100,7 +114,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step val facingBlock = getRelative(position, direction) val x = getX(facingBlock).toDouble() + 0.5 - offset.x - val y = getY(facingBlock).toDouble() + 0.5 + val y = getY(facingBlock).toDouble() + 0.35 val z = getZ(facingBlock).toDouble() + 0.5 - offset.z displayHandler = TextDisplayHandler( @@ -108,7 +122,7 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step x, y, z, - 1.0f, + 0.7f, direction ) } From 9b2b81c2b3ee4d97cd93d13978ad1b419509ef26 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 13 Jul 2024 19:56:51 -0500 Subject: [PATCH 087/500] fix solar pathfinding --- .../server/features/transport/node/power/SolarPanelNode.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 6cd14571dd..e3f24a115f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -20,6 +20,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.firsts import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.core.BlockPos import net.minecraft.world.level.LightLayer @@ -116,7 +117,7 @@ class SolarPanelNode( return } - val solars = neighbors.filterIsInstance() + val solars = neighbors.firsts().filterIsInstance() if (solars.isEmpty()) { exitDistance = -1 return @@ -310,5 +311,5 @@ class SolarPanelNode( } } - override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance" + override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().firsts().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance" } From 2560cb38809f1d6c3ab454c69fa7ccbf9e44e174 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 14 Jul 2024 00:29:40 -0500 Subject: [PATCH 088/500] fix ticking breaking on relog --- .../transport/network/ChunkPowerNetwork.kt | 14 ++++++++------ .../transport/network/ChunkTransportNetwork.kt | 4 +++- .../ion/server/features/world/chunk/ChunkRegion.kt | 3 ++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index 54a4df92ae..ef979e2127 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -29,7 +29,7 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( override val dataVersion: Int = 0 //TODO 1 - private suspend fun tickSolars() { + private suspend fun tickSolarPanels() { for (solarPanel in solarPanels) { runCatching { solarPanel.startStep()?.invoke() }.onFailure { IonServer.slF4JLogger.error("Exception ticking solar panel! $it") @@ -38,15 +38,17 @@ class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork( } } - private suspend fun tickExtractors() = extractors.forEach { (key, extractor) -> - runCatching { extractor.startStep()?.invoke() }.onFailure { - IonServer.slF4JLogger.error("Exception ticking extractor at ${toVec3i(key)}! $it") - it.printStackTrace() + private suspend fun tickExtractors() { + extractors.forEach { (key, extractor) -> + runCatching { extractor.startStep()?.invoke() }.onFailure { + IonServer.slF4JLogger.error("Exception ticking extractor at ${toVec3i(key)}! $it") + it.printStackTrace() + } } } override suspend fun tick() { - tickSolars() + tickSolarPanels() tickExtractors() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index 9940b8cac8..c158e82042 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -72,7 +72,9 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { **/ open fun saveAdditional(pdc: PersistentDataContainer) {} - suspend fun tickIfReady() { if (ready) tick() } + suspend fun tickIfReady() { + if (ready) tick() + } abstract suspend fun tick() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index e864622c6c..5c3d32f333 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -19,7 +19,6 @@ class ChunkRegion(val world: IonWorld) { val size get() = chunks.values.size val tickChunkTransport = IntervalExecutor(4) { - scope.launch { for ((_, chunk) in chunks) { chunk.transportNetwork.tick() @@ -63,6 +62,8 @@ class ChunkRegion(val world: IonWorld) { region.chunks[key] = ionChunk chunk.world.ion.regionPositions[key] = region + + region.world.chunkRegions.add(region) } fun unloadChunk(chunk: IonChunk) { From 964102965d401f1837775b421560cc7535aee6c1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 16 Jul 2024 12:18:52 -0500 Subject: [PATCH 089/500] half finished worldedit listener --- .../transport/ChunkTransportManager.kt | 35 +++----- .../features/transport/IonUpdateExtent.kt | 82 +++++++++++++++++++ .../features/transport/TransportManager.kt | 65 +++++++++++++++ .../network/ChunkTransportNetwork.kt | 32 +++++++- .../server/features/world/chunk/IonChunk.kt | 14 ---- .../server/listener/misc/WorldEditListener.kt | 47 +++++++++++ .../miscellaneous/registrations/Components.kt | 4 + 7 files changed, 238 insertions(+), 41 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index a69039c607..143d82ff02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -1,13 +1,10 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.block.BlockPlaceEvent +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey class ChunkTransportManager( val chunk: IonChunk, @@ -41,23 +38,7 @@ class ChunkTransportManager( // TODO } - fun processBlockRemoval(event: BlockBreakEvent) { - val block = event.block - val key = toBlockKey(block.x, block.y, block.z) - - processBlockRemoval(key) - } - - fun processBlockAddition(event: BlockPlaceEvent) { - val block = event.block - - val key = toBlockKey(block.x, block.y, block.z) - val snapshot = block.snapshot() - - processBlockAddition(key, snapshot) - } - - fun processBlockRemoval(key: Long) { + fun processBlockRemoval(key: BlockKey) { powerNetwork.processBlockRemoval(key) // TODO // TODO @@ -65,11 +46,19 @@ class ChunkTransportManager( // gasGrid.processBlockRemoval(key) } - fun processBlockAddition(key: Long, new: BlockSnapshot) { - powerNetwork.processBlockAddition(key, new) + fun processBlockRemovals(keys: Iterable) { + powerNetwork.processBlockRemovals(keys) + } + + fun processBlockAddition(new: BlockSnapshot) { + powerNetwork.processBlockAddition(new) // TODO // TODO // pipeGrid.processBlockAddition(key, new) // gasGrid.processBlockAddition(key, new) } + + fun processBlockAddition(changes: Iterable) { + powerNetwork.processBlockAdditions(changes) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt new file mode 100644 index 0000000000..4d59ffe292 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt @@ -0,0 +1,82 @@ +package net.horizonsend.ion.server.features.transport + +import com.sk89q.worldedit.EditSession +import com.sk89q.worldedit.bukkit.BukkitAdapter +import com.sk89q.worldedit.extent.AbstractDelegateExtent +import com.sk89q.worldedit.extent.Extent +import com.sk89q.worldedit.function.pattern.Pattern +import com.sk89q.worldedit.math.BlockVector3 +import com.sk89q.worldedit.regions.Region +import com.sk89q.worldedit.world.block.BlockStateHolder +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.World + +class IonUpdateExtent(extent: Extent, val world: World, private val stage: EditSession.Stage) : AbstractDelegateExtent(extent) { + init { + println("Initializing ion update extent") + } + + override fun ?> setBlock(x: Int, y: Int, z: Int, block: T): Boolean { + println("Setting block 1") + println("Got extent: $stage") + + handleUpdate(BlockVector3.at(x, y, z), block) + + return extent.setBlock(x, y, z, block) + } + + @Deprecated("") + override fun ?> setBlock(position: BlockVector3, block: T): Boolean { + println("Setting block 2") + + handleUpdate(position, block) + + return extent.setBlock(position.x, position.y, position.z, block) + } + + override fun ?> setBlocks(region: Region, block: B): Int { + + println("Setting blocks 1") + return extent.setBlocks(region, block) + } + + override fun setBlocks(region: Region, pattern: Pattern): Int { + println("Setting blocks 2") + processPattern(region, pattern) + + return extent.setBlocks(region, pattern) + } + + override fun setBlocks(vset: MutableSet?, pattern: Pattern?): Int { + println("Setting blocks 3") + return extent.setBlocks(vset, pattern) + } + + private fun processPattern(region: Region, pattern: Pattern) { + val newBlocks = region.clone().mapNotNull { position -> + val newBlock = pattern.applyBlock(position) ?: return@mapNotNull null + + val material = BukkitAdapter.adapt(newBlock.blockType) + val blockData = BukkitAdapter.adapt(newBlock.toBaseBlock()) + + BlockSnapshot(world, position.x, position.y, position.z, material, blockData) + } + + TransportManager.handleBlockAdditions(world, newBlocks) + } + + private fun handleUpdate(position: BlockVector3, newBlock: BlockStateHolder<*>?) { + if (newBlock == null) return + + val material = BukkitAdapter.adapt(newBlock.blockType) + val blockData = BukkitAdapter.adapt(newBlock.toBaseBlock()) + + val x = position.x + val y = position.y + val z = position.z + + TransportManager.handleBlockRemoval(world, toBlockKey(x, y, z)) + TransportManager.handleBlockAddition(world, BlockSnapshot(world, x, y, z, material, blockData)) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt new file mode 100644 index 0000000000..2fd56e679b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt @@ -0,0 +1,65 @@ +package net.horizonsend.ion.server.features.transport + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.World +import org.bukkit.event.EventHandler +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPlaceEvent + +object TransportManager : IonServerComponent() { + @EventHandler + fun onBlockBreak(event: BlockBreakEvent) { + val world = event.block.world + val key = toBlockKey(event.block.x, event.block.y, event.block.z) + + handleBlockRemoval(world, key) + } + + @EventHandler + fun onBlockPlace(event: BlockPlaceEvent) { + val world = event.block.world + + handleBlockAddition(world, event.block.snapshot()) + } + + fun handleBlockAddition(world: World, new: BlockSnapshot) { + val chunkX = new.x.shr(4) + val chunkZ = new.z.shr(4) + + val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return + chunk.transportNetwork.processBlockAddition(new) + } + + fun handleBlockAdditions(world: World, newBlocks: Iterable) { + for (new in newBlocks) { + handleBlockAddition(world, new) + } + } + + fun handleBlockRemoval(world: World, key: BlockKey) { + val chunkX = getX(key).shr(4) + val chunkZ = getZ(key).shr(4) + + val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return + + chunk.transportNetwork.processBlockRemoval(key) + } + + fun handleBlockRemovals(world: World, keys: Iterable) { + for (key in keys) { + val chunkX = getX(key).shr(4) + val chunkZ = getZ(key).shr(4) + + val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return + + chunk.transportNetwork.processBlockRemoval(key) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt index c158e82042..7bd8d1c980 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt @@ -48,16 +48,36 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int - open fun processBlockRemoval(key: Long) { manager.scope.launch { withTransportDisabled { + open fun processBlockRemoval(key: BlockKey) { manager.scope.launch { withTransportDisabled { val previousNode = nodes[key] ?: return@withTransportDisabled previousNode.handleRemoval(key) }}} - open fun processBlockAddition(key: Long, new: BlockSnapshot) { manager.scope.launch { + open fun processBlockRemovals(keys: Iterable) { manager.scope.launch { withTransportDisabled { + for (key in keys) { + val previousNode = nodes[key] ?: return@withTransportDisabled + + previousNode.handleRemoval(key) + } + }}} + + open fun processBlockAddition(new: BlockSnapshot) { manager.scope.launch { + if (new.type.isAir) { + processBlockRemoval(toBlockKey(new.x, new.y, new.z)) + + return@launch + } + withTransportDisabled { createNodeFromBlock(new) } }} + open fun processBlockAdditions(changes: Iterable) { manager.scope.launch { withTransportDisabled { + for (new in changes) { + createNodeFromBlock(new) + } + }}} + /** * Handle the creation / loading of the node into memory **/ @@ -258,7 +278,11 @@ abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { protected suspend inline fun withTransportDisabled(crossinline block: suspend () -> Unit) { ready = false - block.invoke() - ready = true + + try { + block.invoke() + } finally { + ready = true + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index e9b5683986..8ca6600605 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -14,8 +14,6 @@ import org.bukkit.Chunk import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.event.EventHandler -import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.INTEGER @@ -112,18 +110,6 @@ class IonChunk( unregisterChunk(event.chunk) } - @EventHandler - fun onBlockBreak(event: BlockBreakEvent) { - val ionChunk = event.block.chunk.ion() - ionChunk.transportNetwork.processBlockRemoval(event) - } - - @EventHandler - fun onBlockBreak(event: BlockPlaceEvent) { - val ionChunk = event.block.chunk.ion() - ionChunk.transportNetwork.processBlockAddition(event) - } - /** * Handles the creation, registration and loading of the chunk in the IonWorld * diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt new file mode 100644 index 0000000000..65f2addd22 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt @@ -0,0 +1,47 @@ +package net.horizonsend.ion.server.listener.misc + +import com.sk89q.worldedit.EditSession +import com.sk89q.worldedit.WorldEdit +import com.sk89q.worldedit.bukkit.BukkitAdapter +import com.sk89q.worldedit.event.Event +import com.sk89q.worldedit.event.extent.EditSessionEvent +import com.sk89q.worldedit.util.eventbus.Subscribe +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.transport.IonUpdateExtent +import org.bukkit.Bukkit + +object WorldEditListener : IonServerComponent(true) { + override fun onEnable() { + if (!Bukkit.getPluginManager().isPluginEnabled("FastAsyncWorldEdit")) return + val worldEdit = runCatching { WorldEdit.getInstance() }.getOrElse { return } + + registerEvents(worldEdit) + } + + private fun registerEvents(worldEdit: WorldEdit) { + registerListener(worldEdit) { event -> + if (event.stage != EditSession.Stage.BEFORE_HISTORY) return@registerListener + + println("Stage: ${event.stage}") + + val world = BukkitAdapter.adapt(event.world) + println("Previous extent: ${event.extent}") + println("Actor: ${event.actor}") + println("event: $event") + + event.extent = IonUpdateExtent(event.extent, world, event.stage) + println("after extent: ${event.extent}") + } + } + + private inline fun registerListener(worldEdit: WorldEdit, crossinline block: (T) -> Unit) { + worldEdit.eventBus.register(object { + val eventClass = T::class.java + + @Subscribe + fun onReceiveEvent(event: T) { + if (eventClass.isInstance(event)) block.invoke(event as? T ?: return) + } + }) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 758fead94b..ecbac9310e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -89,6 +89,7 @@ import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCoold import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.features.transport.TransportConfig +import net.horizonsend.ion.server.features.transport.TransportManager import net.horizonsend.ion.server.features.transport.Wires import net.horizonsend.ion.server.features.transport.pipe.Pipes import net.horizonsend.ion.server.features.transport.pipe.filter.Filters @@ -96,6 +97,7 @@ import net.horizonsend.ion.server.features.tutorial.Tutorials import net.horizonsend.ion.server.features.waypoint.WaypointManager import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.environment.mobs.CustomMobSpawning +import net.horizonsend.ion.server.listener.misc.WorldEditListener import net.horizonsend.ion.server.miscellaneous.registrations.legacy.CustomRecipes import net.horizonsend.ion.server.miscellaneous.utils.Notify @@ -224,6 +226,8 @@ val components: List = listOf( Fleets, ContactsJammingSidebar, CombatTimer, + WorldEditListener, + TransportManager, PlanetTeleportCooldown, MultiBlockDisplay, ) From 7e120724debaa2dfc916d627a80aed0de227143f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 18 Jul 2024 13:13:21 -0500 Subject: [PATCH 090/500] equal splitter node --- .../features/transport/node/NodeType.kt | 5 +- .../node/power/PowerEqualSplitterNode.kt | 75 ++++++++++++++++++- .../transport/node/power/PowerInputNode.kt | 2 +- .../transport/node/power/PowerNodeFactory.kt | 9 ++- .../server/features/transport/step/Step.kt | 6 +- .../transport/step/head/BranchHead.kt | 3 +- .../transport/step/head/HeadHolder.kt | 3 + .../transport/step/head/MultiBranchHead.kt | 18 ++++- .../step/head/power/MultiPowerBranchHead.kt | 4 +- .../step/head/power/SinglePowerBranchHead.kt | 3 +- 10 files changed, 115 insertions(+), 13 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index fc6436182f..f944af9e27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -4,6 +4,7 @@ import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.DirectionalNode import net.horizonsend.ion.server.features.transport.node.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.power.PowerEqualSplitterNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode @@ -18,7 +19,9 @@ enum class NodeType(val clazz: Class) { POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), POWER_FLOW_METER(PowerFlowMeter::class.java), - MERGE_NODE(DirectionalNode::class.java), + POWER_DIRECTIONAL_NODE(DirectionalNode::class.java), +// POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), + POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index 19acb27186..1cd9eee36c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -1,5 +1,76 @@ package net.horizonsend.ion.server.features.transport.node.power -class PowerEqualSplitterNode { - //TODO +import com.manya.pdc.base.EnumDataType +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import net.horizonsend.ion.server.features.transport.step.head.power.MultiPowerBranchHead +import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead +import net.horizonsend.ion.server.features.transport.step.result.ChangeHead +import net.horizonsend.ion.server.features.transport.step.result.StepResult +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Material +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +class PowerEqualSplitterNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { + override var isDead: Boolean = false + override var position: BlockKey by Delegates.notNull() + override val relationships: MutableSet = ObjectOpenHashSet() + + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + this.position = position + } + + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is SourceNode<*> + } + + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } + .randomOrNull() + + + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + val transferable = getTransferableNodes() + + val newHeads = transferable.mapTo(mutableSetOf()) { neighbor -> + MultiBranchHead.MultiHeadHolder { + SinglePowerBranchHead( + holder = it, + lastDirection = neighbor.second, + currentNode = this@PowerEqualSplitterNode, + share = 1.0 + ) + } + } + + return ChangeHead(MultiPowerBranchHead( + holder = head.holder, + 1.0 / transferable.size, + previousNodes = head.previousNodes, + heads = newHeads + )) + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } + + companion object { + val materialDataType = EnumDataType(Material::class.java) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index bc5cfa584c..97395c9a5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -57,7 +57,7 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest } override suspend fun finishChain(head: BranchHead) { - val origin = head.holder.origin + val origin = head.holder.getOrigin() head.markDead() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index cf58bc55bc..0d84eea402 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory @@ -66,7 +67,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory addMergeNode(key, Material.REDSTONE_BLOCK) // Split power evenly -// block.customBlock == CustomBlocks.ALUMINUM_BLOCK -> SplitterNode(this, x, y, z) + CustomBlocks.getByBlockData(snapshot.data) == CustomBlocks.ALUMINUM_BLOCK -> addEqualSplitterNode(key) // Redstone controlled gate // block.type.isRedstoneLamp -> GateNode(this, x, y, z) @@ -193,4 +194,10 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory private constructor( val network: T, - val origin: StepOrigin, + private val stepOrigin: StepOrigin, ) : HeadHolder { override lateinit var head: BranchHead @@ -24,4 +24,8 @@ class Step private constructor( head.stepForward() } } + + override fun getOrigin(): StepOrigin { + return stepOrigin + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt index 2ddaa8513c..9c7d385251 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt @@ -2,10 +2,9 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.Step interface BranchHead { - val holder: Step + val holder: HeadHolder /** Nodes that this head has covered */ val previousNodes: MutableSet diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt index 44deac1d17..96d2fe44f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt @@ -1,7 +1,10 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin interface HeadHolder { var head: BranchHead + + fun getOrigin(): StepOrigin } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt index 1c54b47f90..96b0df712d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt @@ -1,13 +1,29 @@ package net.horizonsend.ion.server.features.transport.step.head import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin +import kotlin.properties.Delegates /** A head which branches into multiple sub-heads */ interface MultiBranchHead : BranchHead { val heads: MutableSet> /** Holder that allows the head within to be replaced */ - class MultiHeadHolder(override var head: BranchHead) : HeadHolder + class MultiHeadHolder() : HeadHolder { + override var head: BranchHead by Delegates.notNull() + + constructor(head: BranchHead) : this() { + this.head = head + } + + constructor(constructHead: (MultiHeadHolder) -> BranchHead) : this() { + this.head = constructHead.invoke(this) + } + + override fun getOrigin(): StepOrigin { + return head.holder.getOrigin() + } + } // Just pass it forward override suspend fun stepForward() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt index 39ce78420e..db24d40f4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.step.head.power import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.Step +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead /** @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead * **/ class MultiPowerBranchHead( - override val holder: Step, + override val holder: HeadHolder, override val share: Double, override val previousNodes: MutableSet = mutableSetOf(), override val heads: MutableSet> = mutableSetOf(), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index 444ac9b393..b4221cadec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwo import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import org.bukkit.block.BlockFace @@ -17,7 +16,7 @@ import org.bukkit.block.BlockFace * **/ class SinglePowerBranchHead( - override val holder: Step, + override val holder: HeadHolder, override var lastDirection: BlockFace, override var currentNode: TransportNode, override val share: Double, From 7a543c60ac97153b6b528c6972cb96c4b2cb208a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 18 Jul 2024 13:26:07 -0500 Subject: [PATCH 091/500] didn't mean to copy that --- .../transport/node/power/PowerEqualSplitterNode.kt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index 1cd9eee36c..f7f1ebb455 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.power -import com.manya.pdc.base.EnumDataType import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship @@ -16,7 +15,6 @@ import net.horizonsend.ion.server.features.transport.step.result.ChangeHead import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -39,7 +37,6 @@ class PowerEqualSplitterNode(override val network: ChunkPowerNetwork) : SingleNo .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { val transferable = getTransferableNodes() @@ -69,8 +66,4 @@ class PowerEqualSplitterNode(override val network: ChunkPowerNetwork) : SingleNo override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } - - companion object { - val materialDataType = EnumDataType(Material::class.java) - } } From 6a9403633f944547cebc1d3f3420820c04291e1b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 18 Jul 2024 13:41:46 -0500 Subject: [PATCH 092/500] work on directional nodes --- .../features/transport/node/NodeType.kt | 3 +- .../transport/node/power/DirectionalNode.kt | 1 + .../node/power/InvertedDirectionalNode.kt | 49 ++++++++++++++++++- .../transport/node/power/PowerNodeFactory.kt | 6 +-- 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index f944af9e27..12ae58d5d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -4,6 +4,7 @@ import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork import net.horizonsend.ion.server.features.transport.node.power.DirectionalNode import net.horizonsend.ion.server.features.transport.node.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.power.PowerEqualSplitterNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter @@ -20,7 +21,7 @@ enum class NodeType(val clazz: Class) { POWER_INPUT_NODE(PowerInputNode::class.java), POWER_FLOW_METER(PowerFlowMeter::class.java), POWER_DIRECTIONAL_NODE(DirectionalNode::class.java), -// POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), + POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), //GAS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt index 69737ebe55..055970847c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt @@ -31,6 +31,7 @@ class DirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, Ste } override fun isTransferableTo(node: TransportNode): Boolean { + if (node is SpongeNode) return false return node !is SourceNode<*> } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index 8c63c87caa..e4a2b93d8a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -1,4 +1,51 @@ package net.horizonsend.ion.server.features.transport.node.power -class InvertedDirectionalNode { +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +class InvertedDirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { + override var isDead: Boolean = false + override var position: BlockKey by Delegates.notNull() + override val relationships: MutableSet = ObjectOpenHashSet() + + constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + this.position = position + } + + override fun isTransferableTo(node: TransportNode): Boolean { + if (node is EndRodNode) return false + return node !is SourceNode<*> + } + + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } + .randomOrNull() + + + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + // Simply move on to the next node + return MoveForward() + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 0d84eea402..6cabfa19e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -190,9 +190,9 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory Date: Thu, 18 Jul 2024 13:55:21 -0500 Subject: [PATCH 093/500] store multiblock manager --- .../multiblock/ChunkMultiblockManager.kt | 3 ++- .../multiblock/entity/MultiblockEntity.kt | 15 +++++++++++++ .../entity/type/ProcessingMultiblockEntity.kt | 4 +++- .../multiblock/newer/MultiblockAccess.kt | 19 ++++++++++------- .../multiblock/newer/MultiblockEntities.kt | 7 +++++-- .../multiblock/type/misc/TestMultiblock.kt | 21 +++++++++++++------ .../powerbank/new/NewPowerBankMultiblock.kt | 4 +++- .../new/NewPowerBankMultiblockTier1.kt | 7 +++++-- .../new/NewPowerBankMultiblockTier2.kt | 7 +++++-- .../new/NewPowerBankMultiblockTier3.kt | 7 +++++-- .../type/starshipweapon/EntityMultiblock.kt | 11 +++++++++- 11 files changed, 79 insertions(+), 26 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index d865e0f11e..5cb8211b93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -83,6 +83,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { // Create new empty data val entity = multiblock.createEntity( + this, PersistentMultiblockData(x, y, z, multiblock, signOffset), chunk.inner.world, x, y, z, @@ -158,7 +159,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { val multiblock = stored.type as EntityMultiblock<*> - val entity = multiblock.createEntity(stored, chunk.inner.world, stored.x, stored.y, stored.z, stored.signOffset) + val entity = multiblock.createEntity(this, stored, chunk.inner.world, stored.x, stored.y, stored.z, stored.signOffset) // No need to save a load addMultiblockEntity(entity, save = false) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 03b45cf666..23411f8daf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -7,6 +8,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.isBlockLoaded import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block @@ -25,6 +27,7 @@ import org.bukkit.block.Sign * @param facing The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( + val manager: ChunkMultiblockManager, val multiblock: Multiblock, var x: Int, @@ -54,6 +57,11 @@ abstract class MultiblockEntity( /** Logic to be run upon the removal of this entity */ open fun handleRemoval() {} + /** Removes this multiblock entity */ + fun remove() { + manager.removeMultiblockEntity(x, y, z) + } + /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ @@ -73,6 +81,13 @@ abstract class MultiblockEntity( return store } + fun isSignLoaded(): Boolean { + val signDirection = facing.oppositeFace + val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) + + return isBlockLoaded(world, signLoc.x, signLoc.y, signLoc.z) + } + /** * Gets the sign of this multiblock **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt index cc2d3abc9b..8c961d69bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity.type +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -15,6 +16,7 @@ import org.bukkit.persistence.PersistentDataType * @param currentProgress The current progress of the process **/ abstract class ProcessingMultiblockEntity( + manager: ChunkMultiblockManager, type: Multiblock, x: Int, y: Int, @@ -23,7 +25,7 @@ abstract class ProcessingMultiblockEntity( signOffset: BlockFace, val requiredProgress: Int, var currentProgress: Int = 0 -) : MultiblockEntity(type, x, y, z, world, signOffset), SyncTickingMultiblockEntity { +) : MultiblockEntity(manager, type, x, y, z, world, signOffset), SyncTickingMultiblockEntity { //TODO // -recipe system diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 6ede0ce0d7..1408495af6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -168,14 +168,17 @@ object MultiblockAccess : IonServerComponent() { } // Create blank multiblock entity - setMultiblockEntity(world, x, y, z, multiblock.createEntity( - PersistentMultiblockData(x, y, z, multiblock, face), - world, - x, - y, - z, - face - )) + setMultiblockEntity(world, x, y, z) { + multiblock.createEntity( + it, + PersistentMultiblockData(x, y, z, multiblock, face), + world, + x, + y, + z, + face + ) + } } return true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt index 3c7ce0944d..713dcb014b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.newer +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk @@ -18,11 +19,13 @@ object MultiblockEntities { /** * Add a new multiblock entity to the chunk **/ - fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, entity: MultiblockEntity): Boolean { + fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, entity: (ChunkMultiblockManager) -> MultiblockEntity): Boolean { val ionChunk = getIonChunk(world, x, y, z) ?: return false ionChunk.region.launch { - ionChunk.multiblockManager.addMultiblockEntity(entity, save = true) + val manager = ionChunk.multiblockManager + + manager.addMultiblockEntity(entity(manager), save = true) } return true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 0228a0c7fe..f20f803e52 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -14,6 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.Entity import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.front import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextDecoration import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer @@ -39,8 +41,9 @@ object TestMultiblock : Multiblock(), EntityMultiblock } abstract class PowerBankEntity( + manager: ChunkMultiblockManager, multiblock: NewPowerBankMultiblock<*>, x: Int, y: Int, @@ -103,7 +105,7 @@ abstract class NewPowerBankMultiblock signDirection: BlockFace, override val maxPower: Int, override var powerUnsafe: Int = 0 - ) : MultiblockEntity(multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { override val powerDisplay: TextDisplayHandler = createTextDisplayHandler() override fun handleRemoval() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt index 128afddf9f..ce01bd33b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new +import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material @@ -10,8 +11,9 @@ import org.bukkit.persistence.PersistentDataType data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { override val tierMaterial = Material.IRON_BLOCK - override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier1Entity { + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier1Entity { return NewPowerBankMultiblockTier1Entity( + manager, this, x, y, @@ -23,6 +25,7 @@ data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock, x: Int, y: Int, @@ -30,5 +33,5 @@ data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&eTier 2") { override val tierMaterial = Material.GOLD_BLOCK - override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier2Entity { + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier2Entity { return NewPowerBankMultiblockTier2Entity( + manager, this, x, y, @@ -23,6 +25,7 @@ data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock, x: Int, y: Int, @@ -30,5 +33,5 @@ data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&bTier 3") { override val tierMaterial = Material.DIAMOND_BLOCK - override fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier3Entity { + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier3Entity { return NewPowerBankMultiblockTier3Entity( + manager, this, x, y, @@ -23,6 +25,7 @@ data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock, x: Int, y: Int, @@ -30,5 +33,5 @@ data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock { /** * Create the multiblock entity using the stored data **/ - fun createEntity(data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): T + fun createEntity( + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + signOffset: BlockFace + ): T fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): T? { val chunkX = x.shr(4) From 7b2eb88b62bbfb566240ae3b2987abe6aff298a1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 18 Jul 2024 14:07:52 -0500 Subject: [PATCH 094/500] simplification --- ...impleTextDisplayPoweredMultiblockEntity.kt | 30 ++++++++++--------- .../powerbank/new/NewPowerBankMultiblock.kt | 9 +++--- .../new/NewPowerBankMultiblockTier1.kt | 26 ++++++++-------- .../new/NewPowerBankMultiblockTier2.kt | 26 ++++++++-------- .../new/NewPowerBankMultiblockTier3.kt | 26 ++++++++-------- 5 files changed, 57 insertions(+), 60 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt index f396015682..1157e9f469 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt @@ -14,22 +14,24 @@ interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity { powerDisplay.setText(formatPower()) } - fun createTextDisplayHandler(): TextDisplayHandler { - require(this is MultiblockEntity) + companion object { + fun createTextDisplayHandler(entity: SimpleTextDisplayPoweredMultiblockEntity): TextDisplayHandler { + require(entity is MultiblockEntity) - val signDirection = facing.oppositeFace - val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) + val signDirection = entity.facing.oppositeFace + val signLoc = Vec3i(entity.x, entity.y, entity.z) + Vec3i(signDirection.modX, 0, signDirection.modZ) - // 70% of the way through the block - val offset = signDirection.direction.multiply(0.39) + // 70% of the way through the block + val offset = signDirection.direction.multiply(0.39) - return TextDisplayHandler( - world, - signLoc.x.toDouble() + 0.5 - offset.x, - signLoc.y.toDouble() + 0.4, - signLoc.z.toDouble() + 0.5 - offset.z, - 0.5f, - signDirection - ) + return TextDisplayHandler( + entity.world, + signLoc.x.toDouble() + 0.5 - offset.x, + signLoc.y.toDouble() + 0.4, + signLoc.z.toDouble() + 0.5 - offset.z, + 0.5f, + signDirection + ) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 7e5d3debec..df63051339 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock @@ -20,7 +21,7 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataType -abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock, InteractableMultiblock { +abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock, InteractableMultiblock { abstract val tierMaterial: Material override val name = "newpowerbank" @@ -95,9 +96,9 @@ abstract class NewPowerBankMultiblock player.information("Unsafe Power: ${entity.powerUnsafe}") } - abstract class PowerBankEntity( + class PowerBankEntity( manager: ChunkMultiblockManager, - multiblock: NewPowerBankMultiblock<*>, + multiblock: NewPowerBankMultiblock, x: Int, y: Int, z: Int, @@ -106,7 +107,7 @@ abstract class NewPowerBankMultiblock override val maxPower: Int, override var powerUnsafe: Int = 0 ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { - override val powerDisplay: TextDisplayHandler = createTextDisplayHandler() + override val powerDisplay: TextDisplayHandler = createTextDisplayHandler(this) override fun handleRemoval() { powerDisplay.remove() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt index ce01bd33b2..b7702c0ea8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt @@ -8,11 +8,19 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataType -data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { +data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { override val tierMaterial = Material.IRON_BLOCK - override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier1Entity { - return NewPowerBankMultiblockTier1Entity( + override fun createEntity( + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + signOffset: BlockFace + ): PowerBankEntity { + return PowerBankEntity( manager, this, x, @@ -20,18 +28,8 @@ data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - powerUnsafe: Int - ) : PowerBankEntity(manager, multiblock, x, y, z, world, signDirection, 300_000, powerUnsafe) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt index 11e7315640..bdfee38b0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt @@ -8,11 +8,19 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataType -data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&eTier 2") { +data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&eTier 2") { override val tierMaterial = Material.GOLD_BLOCK - override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier2Entity { - return NewPowerBankMultiblockTier2Entity( + override fun createEntity( + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + signOffset: BlockFace + ): PowerBankEntity { + return PowerBankEntity( manager, this, x, @@ -20,18 +28,8 @@ data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - powerUnsafe: Int - ) : PowerBankEntity(manager, multiblock, x, y, z, world, signDirection, 350_000, powerUnsafe) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt index 954bfe8af6..d77e9b0a16 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt @@ -8,11 +8,19 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataType -data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock("&bTier 3") { +data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock("&bTier 3") { override val tierMaterial = Material.DIAMOND_BLOCK - override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): NewPowerBankMultiblockTier3Entity { - return NewPowerBankMultiblockTier3Entity( + override fun createEntity( + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + signOffset: BlockFace + ): PowerBankEntity { + return PowerBankEntity( manager, this, x, @@ -20,18 +28,8 @@ data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - powerUnsafe: Int - ) : PowerBankEntity(manager, multiblock, x, y, z, world, signDirection, 500_000_000, powerUnsafe) } From 199cb784e0e4befe4abd7d827a061e88ca362edf Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 19 Jul 2024 20:09:38 -0500 Subject: [PATCH 095/500] gas network files --- .../multiblock/ChunkMultiblockManager.kt | 10 ++-- .../multiblock/newer/MultiblockAccess.kt | 19 ++----- .../transport/network/ChunkGasNetwork.kt | 29 ++++++++++ .../transport/network/ChunkPowerNetwork.kt | 7 ++- .../features/transport/node/NodeType.kt | 4 +- .../features/transport/node/NodeUtils.kt | 7 ++- .../transport/node/gas/GasDirectionalNode.kt | 4 ++ .../transport/node/gas/GasExtractorNode.kt | 4 ++ .../transport/node/gas/GasFilterNode.kt | 4 ++ .../transport/node/gas/GasFlowMeter.kt | 4 ++ .../transport/node/gas/GasInputNode.kt | 4 ++ .../node/gas/GasInvertedDirectionalNode.kt | 4 ++ .../transport/node/gas/GasNodeFactory.kt | 12 ++++ .../transport/node/gas/GasValveNode.kt | 4 ++ .../transport/node/gas/LightningRodNode.kt | 4 ++ .../transport/node/gas/PowerJunctionNode.kt | 4 ++ ...ctionalNode.kt => PowerDirectionalNode.kt} | 2 +- .../node/power/PowerExtractorNode.kt | 2 +- .../transport/node/power/PowerInputNode.kt | 4 +- .../transport/node/power/PowerNodeFactory.kt | 2 +- .../transport/node/power/SolarPanelNode.kt | 2 +- .../transport/step/head/gas/GasBranchHead.kt | 5 ++ .../step/head/gas/MultiGasBranchHead.kt | 18 ++++++ .../step/head/gas/SingleGasBranchHead.kt | 56 +++++++++++++++++++ .../transport/step/origin/StepOrigin.kt | 4 +- .../step/origin/gas/ExtractedGasOrigin.kt | 9 +++ .../{ => power}/ExtractorPowerOrigin.kt | 3 +- .../step/origin/{ => power}/PowerOrigin.kt | 2 +- .../origin/{ => power}/SolarPowerOrigin.kt | 3 +- 29 files changed, 200 insertions(+), 36 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/{DirectionalNode.kt => PowerDirectionalNode.kt} (96%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/GasBranchHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/{ => power}/ExtractorPowerOrigin.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/{ => power}/PowerOrigin.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/{ => power}/SolarPowerOrigin.kt (90%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 5cb8211b93..4cacc3d073 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataType @@ -69,13 +70,10 @@ class ChunkMultiblockManager(val chunk: IonChunk) { /** * Add a new multiblock to the chunk data **/ - suspend fun addNewMultiblockEntity(multiblock: EntityMultiblock<*>, sign: Sign) { + suspend fun addNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace) { // Allow smart cast multiblock as Multiblock - val (x, y, z) = Multiblock.getOrigin(sign) - val signOffset = sign.getFacing() - if (isOccupied(x, y, z)) { log.warn("Attempted to place a multiblock where one already existed!") return @@ -84,10 +82,10 @@ class ChunkMultiblockManager(val chunk: IonChunk) { // Create new empty data val entity = multiblock.createEntity( this, - PersistentMultiblockData(x, y, z, multiblock, signOffset), + PersistentMultiblockData(x, y, z, multiblock, face), chunk.inner.world, x, y, z, - signOffset + face ) // Place the entity into the chunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 1408495af6..85aaf861d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -11,12 +11,11 @@ import net.horizonsend.ion.common.utils.text.subStringBetween import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.getMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.removeMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.setMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -167,17 +166,11 @@ object MultiblockAccess : IonServerComponent() { log.warn("Attempted to place multiblock entity where one was already present!") } - // Create blank multiblock entity - setMultiblockEntity(world, x, y, z) { - multiblock.createEntity( - it, - PersistentMultiblockData(x, y, z, multiblock, face), - world, - x, - y, - z, - face - ) + val chunkX = x.shr(4) + val chunkZ = z.shr(4) + + world.ion.getChunk(chunkX, chunkZ)?.let { + it.region.launch { it.multiblockManager.addNewMultiblockEntity(multiblock, x, y, z, face) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt new file mode 100644 index 0000000000..fae1ba19d6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt @@ -0,0 +1,29 @@ +package net.horizonsend.ion.server.features.transport.network + +import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.gas.GasExtractorNode +import net.horizonsend.ion.server.features.transport.node.gas.GasNodeFactory +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.GAS_TRANSPORT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.NamespacedKey +import java.util.concurrent.ConcurrentHashMap + +class ChunkGasNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { + override val namespacedKey: NamespacedKey = GAS_TRANSPORT + override val type: NetworkType = NetworkType.GAS + override val nodeFactory = GasNodeFactory(this) + + val extractors: ConcurrentHashMap = ConcurrentHashMap() + + override val dataVersion: Int = 0 + + override suspend fun tick() { + + } + + override fun clearData() { + nodes.clear() + extractors.clear() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt index ef979e2127..ac1646a683 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt @@ -10,7 +10,8 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNo import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.NamespacedKey @@ -19,10 +20,10 @@ import java.util.concurrent.ConcurrentHashMap class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { override val type: NetworkType = NetworkType.POWER - override val namespacedKey: NamespacedKey = NamespacedKeys.POWER_TRANSPORT + override val namespacedKey: NamespacedKey = POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) - val extractors: ConcurrentHashMap = ConcurrentHashMap() + val extractors: ConcurrentHashMap = ConcurrentHashMap() /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 12ae58d5d6..e623c704c6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -2,9 +2,9 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork -import net.horizonsend.ion.server.features.transport.node.power.DirectionalNode import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode +import net.horizonsend.ion.server.features.transport.node.power.PowerDirectionalNode import net.horizonsend.ion.server.features.transport.node.power.PowerEqualSplitterNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter @@ -20,7 +20,7 @@ enum class NodeType(val clazz: Class) { POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), POWER_INPUT_NODE(PowerInputNode::class.java), POWER_FLOW_METER(PowerFlowMeter::class.java), - POWER_DIRECTIONAL_NODE(DirectionalNode::class.java), + POWER_DIRECTIONAL_NODE(PowerDirectionalNode::class.java), POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index da7340f253..ce68c4b232 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -62,7 +62,12 @@ enum class NetworkType { override fun get(chunk: IonChunk): ChunkTransportNetwork { return chunk.transportNetwork.powerNetwork } - } + }, + GAS { + override fun get(chunk: IonChunk): ChunkTransportNetwork { + return chunk.transportNetwork.powerNetwork + } + }, ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt new file mode 100644 index 0000000000..a599aa1c96 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasDirectionalNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt new file mode 100644 index 0000000000..eea5cb75f0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasExtractorNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt new file mode 100644 index 0000000000..897a5a8f2e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasFilterNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt new file mode 100644 index 0000000000..f98cc21bc9 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasFlowMeter { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt new file mode 100644 index 0000000000..943a1c090e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasInputNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt new file mode 100644 index 0000000000..73a23dce11 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasInvertedDirectionalNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt new file mode 100644 index 0000000000..0ab8970908 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt @@ -0,0 +1,12 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.transport.network.ChunkGasNetwork +import net.horizonsend.ion.server.features.transport.node.NodeFactory +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +class GasNodeFactory(network: ChunkGasNetwork) : NodeFactory(network) { + override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt new file mode 100644 index 0000000000..8cd972c66f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class GasValveNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt new file mode 100644 index 0000000000..7e5d7465b1 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class LightningRodNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt new file mode 100644 index 0000000000..b6a5a22ec3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +class PowerJunctionNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index 055970847c..a62790e5fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/DirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -19,7 +19,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class DirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { +class PowerDirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() private var variant: Material by Delegates.notNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 63b4d1fa64..dab4e10e8c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin +import net.horizonsend.ion.server.features.transport.step.origin.power.ExtractorPowerOrigin import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 97395c9a5b..50af83093d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.origin.ExtractorPowerOrigin -import net.horizonsend.ion.server.features.transport.step.origin.PowerOrigin +import net.horizonsend.ion.server.features.transport.step.origin.power.ExtractorPowerOrigin +import net.horizonsend.ion.server.features.transport.step.origin.power.PowerOrigin import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 6cabfa19e2..7fc6d2784c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -184,7 +184,7 @@ class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory, + override val share: Double, + override val previousNodes: MutableSet = mutableSetOf(), + override val heads: MutableSet> = mutableSetOf(), +) : MultiBranchHead, GasBranchHead + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt new file mode 100644 index 0000000000..d079928670 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt @@ -0,0 +1,56 @@ +package net.horizonsend.ion.server.features.transport.step.head.gas + +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork as ChunkTransportNetwork1 +import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.DestinationNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.head.HeadHolder +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import org.bukkit.block.BlockFace + +/** + * Transferred power down a single path. + * + * + **/ +class SingleGasBranchHead( + override val holder: HeadHolder, + override var lastDirection: BlockFace, + override var currentNode: TransportNode, + override val share: Double, + override val previousNodes: MutableSet = mutableSetOf() +) : SingleBranchHead, GasBranchHead { + private var isDead = false + + override fun markDead() { + isDead = true + } + + override fun isDead(): Boolean = isDead + + @Suppress("UNCHECKED_CAST") + override suspend fun stepForward() { + val node = currentNode + + if (tryCast>(node) { finishChain(this@SingleGasBranchHead) }) return + + // All other nodes handle steps transferring in / out + node as StepHandler + + val result = node.handleHeadStep(this as SingleBranchHead) + + result.apply(holder as HeadHolder) + } + + // Get around runtime type erasure + private inline fun tryCast(instance: Any?, block: T.() -> Unit): Boolean { + if (instance is T) { + block(instance) + return true + } + + return false + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt index 9b7038c7b9..8183393f0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt @@ -2,5 +2,5 @@ package net.horizonsend.ion.server.features.transport.step.origin import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork -interface StepOrigin { -} +interface StepOrigin + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt new file mode 100644 index 0000000000..15cacc8269 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.features.transport.step.origin.gas + +import net.horizonsend.ion.server.features.transport.network.ChunkGasNetwork +import net.horizonsend.ion.server.features.transport.node.gas.GasExtractorNode +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin + +class ExtractedGasOrigin( + val extractorNode: GasExtractorNode +) : StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt index dc7a3ffb20..aa696a49e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/ExtractorPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt @@ -1,9 +1,10 @@ -package net.horizonsend.ion.server.features.transport.step.origin +package net.horizonsend.ion.server.features.transport.step.origin.power import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class ExtractorPowerOrigin( val extractorNode: PowerExtractorNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt index a3c967d80a..82f8025e2a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/PowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.step.origin +package net.horizonsend.ion.server.features.transport.step.origin.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt index 9a4e06d410..138f620356 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/SolarPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt @@ -1,8 +1,9 @@ -package net.horizonsend.ion.server.features.transport.step.origin +package net.horizonsend.ion.server.features.transport.step.origin.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin, PowerOrigin { override val transferLimit: Int = Int.MAX_VALUE From dcf0a90a70c1b41199ee6d5d8f7039d90e7acba9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 20 Jul 2024 01:50:27 -0500 Subject: [PATCH 096/500] decouple transport networks from chunks --- .../server/command/admin/IonChunkCommand.kt | 6 +- .../multiblock/ChunkMultiblockManager.kt | 2 +- .../transport/ChunkTransportManager.kt | 23 +- .../network/ChunkTransportNetwork.kt | 288 ------------------ .../{ChunkGasNetwork.kt => GasNetwork.kt} | 4 +- .../{ChunkPowerNetwork.kt => PowerNetwork.kt} | 4 +- .../transport/network/TransportNetwork.kt | 127 ++++++++ .../network/holders/ChunkNetworkHolder.kt | 187 ++++++++++++ .../network/holders/NetworkHolder.kt | 36 +++ .../network/holders/ShipNetworkHolder.kt | 43 +++ .../features/transport/node/NodeFactory.kt | 4 +- .../features/transport/node/NodeType.kt | 4 +- .../features/transport/node/NodeUtils.kt | 22 +- .../features/transport/node/TransportNode.kt | 9 +- .../transport/node/gas/GasNodeFactory.kt | 4 +- .../transport/node/power/EndRodNode.kt | 10 +- .../node/power/InvertedDirectionalNode.kt | 10 +- .../node/power/PowerDirectionalNode.kt | 10 +- .../node/power/PowerEqualSplitterNode.kt | 10 +- .../node/power/PowerExtractorNode.kt | 14 +- .../transport/node/power/PowerFlowMeter.kt | 10 +- .../transport/node/power/PowerInputNode.kt | 21 +- .../transport/node/power/PowerNodeFactory.kt | 4 +- .../transport/node/power/SolarPanelNode.kt | 14 +- .../transport/node/power/SpongeNode.kt | 10 +- .../transport/node/type/DestinationNode.kt | 4 +- .../transport/node/type/SourceNode.kt | 4 +- .../transport/node/type/StepHandler.kt | 4 +- .../server/features/transport/step/Step.kt | 4 +- .../transport/step/head/BranchHead.kt | 4 +- .../transport/step/head/HeadHolder.kt | 4 +- .../transport/step/head/MultiBranchHead.kt | 6 +- .../transport/step/head/SingleBranchHead.kt | 4 +- .../step/head/gas/MultiGasBranchHead.kt | 8 +- .../step/head/gas/SingleGasBranchHead.kt | 16 +- .../step/head/power/MultiPowerBranchHead.kt | 8 +- .../step/head/power/SinglePowerBranchHead.kt | 16 +- .../transport/step/origin/StepOrigin.kt | 4 +- .../step/origin/gas/ExtractedGasOrigin.kt | 4 +- .../step/origin/power/ExtractorPowerOrigin.kt | 4 +- .../step/origin/power/SolarPowerOrigin.kt | 4 +- .../transport/step/result/ChangeHead.kt | 4 +- .../transport/step/result/EndBranch.kt | 4 +- .../transport/step/result/MoveForward.kt | 4 +- .../transport/step/result/StepResult.kt | 4 +- 45 files changed, 559 insertions(+), 431 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/{ChunkGasNetwork.kt => GasNetwork.kt} (85%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/{ChunkPowerNetwork.kt => PowerNetwork.kt} (94%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 92fa6caebc..ce69698c9a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion @@ -86,7 +86,7 @@ object IonChunkCommand : SLCommand() { sender.information("${grid.nodes.values.distinct().size} unique node(s).") when (grid) { - is ChunkPowerNetwork -> { + is PowerNetwork -> { sender.information("${grid.solarPanels.size} solar panels") sender.information("${grid.extractors.size} extractors") sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") @@ -112,7 +112,7 @@ object IonChunkCommand : SLCommand() { grid.nodes.clear() when (grid) { - is ChunkPowerNetwork -> { + is PowerNetwork -> { grid.extractors.clear() grid.solarPanels.clear() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt index 4cacc3d073..027afdbf53 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt @@ -92,7 +92,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { addMultiblockEntity(entity) if (entity is PoweredMultiblockEntity) { - chunk.transportNetwork.powerNetwork.handleNewPoweredMultiblock(entity) + chunk.transportNetwork.powerNetwork.network.handleNewPoweredMultiblock(entity) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 143d82ff02..0d7ee1ae7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -1,7 +1,8 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.network.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -10,24 +11,24 @@ class ChunkTransportManager( val chunk: IonChunk, ) { val scope = ChunkRegion.scope - val powerNetwork = ChunkPowerNetwork(this) -// val pipeGrid = ChunkPowerNetwork(this) // TODO -// val gasGrid = ChunkPowerNetwork(this) // TODO + val powerNetwork = ChunkNetworkHolder(this) { PowerNetwork(it) } +// val pipeGrid = PowerNetwork(this) // TODO +// val gasGrid = PowerNetwork(this) // TODO fun setup() { - powerNetwork.loadNetwork() + powerNetwork.handleLoad() // TODO // TODO } suspend fun tick() { - powerNetwork.tickIfReady() + powerNetwork.network.tickIfReady() // TODO // TODO } fun onUnload() { - powerNetwork.onUnload() + powerNetwork.handleUnload() // TODO // TODO } @@ -39,7 +40,7 @@ class ChunkTransportManager( } fun processBlockRemoval(key: BlockKey) { - powerNetwork.processBlockRemoval(key) + powerNetwork.network.processBlockRemoval(key) // TODO // TODO // pipeGrid.processBlockRemoval(key) @@ -47,11 +48,11 @@ class ChunkTransportManager( } fun processBlockRemovals(keys: Iterable) { - powerNetwork.processBlockRemovals(keys) + powerNetwork.network.processBlockRemovals(keys) } fun processBlockAddition(new: BlockSnapshot) { - powerNetwork.processBlockAddition(new) + powerNetwork.network.processBlockAddition(new) // TODO // TODO // pipeGrid.processBlockAddition(key, new) @@ -59,6 +60,6 @@ class ChunkTransportManager( } fun processBlockAddition(changes: Iterable) { - powerNetwork.processBlockAdditions(changes) + powerNetwork.network.processBlockAdditions(changes) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt deleted file mode 100644 index 7bd8d1c980..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkTransportNetwork.kt +++ /dev/null @@ -1,288 +0,0 @@ -package net.horizonsend.ion.server.features.transport.network - -import kotlinx.coroutines.Job -import kotlinx.coroutines.joinAll -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.NodeFactory -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import org.bukkit.NamespacedKey -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER -import java.util.concurrent.ConcurrentHashMap - -abstract class ChunkTransportNetwork(val manager: ChunkTransportManager) { - protected var ready: Boolean = false - - val nodes: ConcurrentHashMap = ConcurrentHashMap() - - val world get() = manager.chunk.world - - protected val chunkPDC get() = manager.chunk.inner.persistentDataContainer - protected val networkPDC get() = chunkPDC.get( - namespacedKey, - TAG_CONTAINER - ) ?: run { - IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") - - chunkPDC.adapterContext.newPersistentDataContainer() - } - - protected abstract val namespacedKey: NamespacedKey - protected abstract val type: NetworkType - abstract val nodeFactory: NodeFactory<*> - abstract val dataVersion: Int - - open fun processBlockRemoval(key: BlockKey) { manager.scope.launch { withTransportDisabled { - val previousNode = nodes[key] ?: return@withTransportDisabled - - previousNode.handleRemoval(key) - }}} - - open fun processBlockRemovals(keys: Iterable) { manager.scope.launch { withTransportDisabled { - for (key in keys) { - val previousNode = nodes[key] ?: return@withTransportDisabled - - previousNode.handleRemoval(key) - } - }}} - - open fun processBlockAddition(new: BlockSnapshot) { manager.scope.launch { - if (new.type.isAir) { - processBlockRemoval(toBlockKey(new.x, new.y, new.z)) - - return@launch - } - - withTransportDisabled { createNodeFromBlock(new) } - }} - - open fun processBlockAdditions(changes: Iterable) { manager.scope.launch { withTransportDisabled { - for (new in changes) { - createNodeFromBlock(new) - } - }}} - - /** - * Handle the creation / loading of the node into memory - **/ - open suspend fun createNodeFromBlock(block: BlockSnapshot) { - val key = toBlockKey(block.x, block.y, block.z) - - withTransportDisabled { nodeFactory.create(key, block) } - } - - /** - * Save additional metadata into the network PDC - **/ - open fun saveAdditional(pdc: PersistentDataContainer) {} - - suspend fun tickIfReady() { - if (ready) tick() - } - - abstract suspend fun tick() - - abstract fun clearData() - - /** - * Logic for when the holding chunk is unloaded - **/ - fun onUnload() { - // Break cross chunk relations - breakAllRelations() - - save(manager.chunk.inner.persistentDataContainer.adapterContext) - } - - /** - * Builds the transportNetwork - * - * Existing data will be loaded from the chunk's persistent data container, relations between nodes will be built, and any finalization will be performed - **/ - fun loadNetwork() { - val adapterContext = chunkPDC.adapterContext - - // Load data sync - val good = loadData() - - manager.scope.launch { - // Handle cases of data corruption - if (!good) { - clearData() - collectAllNodes().join() - - // Save rebuilt data - save(adapterContext) - } - - buildRelations() - finalizeNodes() - - ready = true - } - } - - /** - * Load stored node data from the chunk - * - * @return Whether the data was intact, or up to date - **/ - fun loadData(): Boolean { - val version = networkPDC.getOrDefault(DATA_VERSION, PersistentDataType.INTEGER, 0) - - if (version < dataVersion) { - IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained outdated data! It will be rebuilt") - return false - } - - // Deserialize once - val nodeData = networkPDC.getOrDefault(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).map { - runCatching { TransportNode.load(it, this) }.onFailure { - IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained corrupted data! It will be rebuilt") - it.printStackTrace() - }.getOrElse { - return false - } - } - - nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { - IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} loading node into network!") - it.printStackTrace() - return false - } } - - return true - } - - fun save(adapterContext: PersistentDataAdapterContext) { - val container = adapterContext.newPersistentDataContainer() - - val serializedNodes: MutableMap = mutableMapOf() - - nodes.values.distinct().forEach { node -> - serializedNodes[node] = node.serialize(adapterContext, node) - } - - if (serializedNodes.isNotEmpty()) { - manager.chunk.inner.minecraft.isUnsaved = true - } - - container.set(NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.toTypedArray()) - container.set(DATA_VERSION, PersistentDataType.INTEGER, dataVersion) - saveAdditional(container) - - // Save the network PDC - chunkPDC.set(namespacedKey, TAG_CONTAINER, container) - } - - /** - * Build node data from an unregistered state - **/ - private fun collectAllNodes(): Job = manager.scope.launch { - // Parallel collect the nodes of each section - manager.chunk.sections.map { (y, _) -> - launch { collectSectionNodes(y) } - }.joinAll() - } - - /** - * Collect all nodes in this chunk section - * - * Iterate the section for possible nodes, handle creation - **/ - private suspend fun collectSectionNodes(sectionY: Int) { - val originX = manager.chunk.originX - val originY = sectionY.shl(4) - manager.chunk.inner.world.minHeight - val originZ = manager.chunk.originZ - - for (x: Int in 0..15) { - val realX = originX + x - - for (y: Int in 0..15) { - val realY = originY + y - - for (z: Int in 0..15) { - val realZ = originZ + z - - val snapshot = getBlockSnapshotAsync(manager.chunk.world, realX, realY, realZ) ?: continue - - createNodeFromBlock(snapshot) - } - } - } - } - - /** - * Get the neighbors of a node - **/ - suspend fun buildRelations() { - for ((key, node) in nodes) { - node.buildRelations(key) - } - } - - /** - * Handles any cleanup tasks at the end of loading - **/ - open fun finalizeNodes() {} - - fun breakAllRelations() { - runBlocking { nodes.values.forEach { it.clearRelations() } } - } - - fun getNode(x: Int, y: Int, z: Int): TransportNode? { - val key = toBlockKey(x, y, z) - return nodes[key] - } - - /** - * Gets a node from this chunk, or a direct neighbor, if loaded - **/ - fun getNode(key: BlockKey, allowNeighborChunks: Boolean = true): TransportNode? { - val chunkX = getX(key).shr(4) - val chunkZ = getZ(key).shr(4) - - val isThisChunk = chunkX == manager.chunk.x && chunkZ == manager.chunk.z - - if (!allowNeighborChunks && isThisChunk) return null - - if (isThisChunk) { - return nodes[key] - } - - val xDiff = manager.chunk.x - chunkX - val zDiff = manager.chunk.z - chunkZ - - if (xDiff > 1 || xDiff < -1) return null - if (zDiff > 1 || zDiff < -1) return null - - val chunk = IonChunk[world, chunkX, chunkZ] ?: return null - return type.get(chunk).nodes[key] - } - - protected suspend inline fun withTransportDisabled(crossinline block: suspend () -> Unit) { - ready = false - - try { - block.invoke() - } finally { - ready = true - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/GasNetwork.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/GasNetwork.kt index fae1ba19d6..54b7314902 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkGasNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/GasNetwork.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.network -import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.gas.GasExtractorNode import net.horizonsend.ion.server.features.transport.node.gas.GasNodeFactory @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap -class ChunkGasNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { +class GasNetwork(holder: NetworkHolder) : TransportNetwork(holder) { override val namespacedKey: NamespacedKey = GAS_TRANSPORT override val type: NetworkType = NetworkType.GAS override val nodeFactory = GasNodeFactory(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt index ac1646a683..c29d412e81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/ChunkPowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.network import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode @@ -18,7 +18,7 @@ import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -class ChunkPowerNetwork(manager: ChunkTransportManager) : ChunkTransportNetwork(manager) { +class PowerNetwork(holder: NetworkHolder) : TransportNetwork(holder) { override val type: NetworkType = NetworkType.POWER override val namespacedKey: NamespacedKey = POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt new file mode 100644 index 0000000000..0773b57084 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt @@ -0,0 +1,127 @@ +package net.horizonsend.ion.server.features.transport.network + +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot +import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.NodeFactory +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataContainer +import java.util.concurrent.ConcurrentHashMap + +abstract class TransportNetwork(val holder: NetworkHolder<*>) { + var ready: Boolean = false + + val nodes: ConcurrentHashMap = ConcurrentHashMap() + + val world get() = holder.getWorld() + + abstract val namespacedKey: NamespacedKey + abstract val type: NetworkType + abstract val nodeFactory: NodeFactory<*> + abstract val dataVersion: Int + + open fun processBlockRemoval(key: BlockKey) { holder.scope.launch { withTransportDisabled { + val previousNode = nodes[key] ?: return@withTransportDisabled + + previousNode.handleRemoval(key) + }}} + + open fun processBlockRemovals(keys: Iterable) { holder.scope.launch { withTransportDisabled { + for (key in keys) { + val previousNode = nodes[key] ?: return@withTransportDisabled + + previousNode.handleRemoval(key) + } + }}} + + open fun processBlockAddition(new: BlockSnapshot) { holder.scope.launch { + if (new.type.isAir) { + processBlockRemoval(toBlockKey(new.x, new.y, new.z)) + + return@launch + } + + withTransportDisabled { createNodeFromBlock(new) } + }} + + open fun processBlockAdditions(changes: Iterable) { holder.scope.launch { withTransportDisabled { + for (new in changes) { + createNodeFromBlock(new) + } + }}} + + /** + * Handle the creation / loading of the node into memory + **/ + suspend fun createNodeFromBlock(block: BlockSnapshot) { + val key = toBlockKey(block.x, block.y, block.z) + + withTransportDisabled { nodeFactory.create(key, block) } + } + + /** + * Save additional metadata into the network PDC + **/ + open fun saveAdditional(pdc: PersistentDataContainer) {} + + suspend fun tickIfReady() { + if (ready) tick() + } + + abstract suspend fun tick() + + abstract fun clearData() + + /** + * Logic for when the holding chunk is unloaded + **/ + fun onUnload() { + // Break cross chunk relations + breakAllRelations() + } + + /** + * Get the neighbors of a node + **/ + suspend fun buildRelations() { + for ((key, node) in nodes) { + node.buildRelations(key) + } + } + + /** + * Handles any cleanup tasks at the end of loading + **/ + open fun finalizeNodes() {} + + fun breakAllRelations() { + runBlocking { nodes.values.forEach { it.clearRelations() } } + } + + fun getNode(x: Int, y: Int, z: Int, allowNeighborChunks: Boolean = true): TransportNode? { + val key = toBlockKey(x, y, z) + return getNode(key, allowNeighborChunks) + } + + /** + * Gets a node from this chunk, or a direct neighbor, if loaded + **/ + fun getNode(key: BlockKey, allowNeighborChunks: Boolean = true): TransportNode? { + return if (allowNeighborChunks) holder.getGlobalNode(key) else holder.getInternalNode(key) + } + + protected suspend inline fun withTransportDisabled(crossinline block: suspend () -> Unit) { + ready = false + + try { + block.invoke() + } finally { + ready = true + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt new file mode 100644 index 0000000000..c7ea86f535 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt @@ -0,0 +1,187 @@ +package net.horizonsend.ion.server.features.transport.network.holders + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.joinAll +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import org.bukkit.World +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { + override var network: T by Delegates.notNull(); private set + + constructor(manager: ChunkTransportManager, network: (ChunkNetworkHolder) -> T) : this(manager) { + this.network = network(this) + } + + override val scope: CoroutineScope = manager.scope + + override fun getWorld(): World = manager.chunk.world + + override fun getGlobalNode(key: BlockKey): TransportNode? { + val chunkX = getX(key).shr(4) + val chunkZ = getZ(key).shr(4) + + val isThisChunk = chunkX == manager.chunk.x && chunkZ == manager.chunk.z + + if (isThisChunk) { + return network.nodes[key] + } + + val xDiff = manager.chunk.x - chunkX + val zDiff = manager.chunk.z - chunkZ + + if (xDiff > 1 || xDiff < -1) return null + if (zDiff > 1 || zDiff < -1) return null + + val chunk = IonChunk[getWorld(), chunkX, chunkZ] ?: return null + return network.type.get(chunk).nodes[key] + } + + override fun getInternalNode(key: BlockKey): TransportNode? { + return network.nodes[key] + } + + private val chunkPDC get() = manager.chunk.inner.persistentDataContainer + private val networkPDC get() = chunkPDC.get( + network.namespacedKey, + PersistentDataType.TAG_CONTAINER + ) ?: run { + IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") + + chunkPDC.adapterContext.newPersistentDataContainer() + } + + override fun handleLoad() { + // Load data sync + val good = loadData() + + manager.scope.launch { + val adapterContext = chunkPDC.adapterContext + + // Handle cases of data corruption + if (!good) { + network.clearData() + collectAllNodes().join() + + // Save rebuilt data + save(adapterContext) + } + + network.buildRelations() + network.finalizeNodes() + + network.ready = true + } + } + + override fun handleUnload() { + network.onUnload() + + save(manager.chunk.inner.persistentDataContainer.adapterContext) + } + + fun save(adapterContext: PersistentDataAdapterContext) { + val container = adapterContext.newPersistentDataContainer() + + val serializedNodes: MutableMap = mutableMapOf() + + network.nodes.values.distinct().forEach { node -> + serializedNodes[node] = node.serialize(adapterContext, node) + } + + if (serializedNodes.isNotEmpty()) { + manager.chunk.inner.minecraft.isUnsaved = true + } + + container.set(NamespacedKeys.NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.toTypedArray()) + container.set(NamespacedKeys.DATA_VERSION, PersistentDataType.INTEGER, network.dataVersion) + network.saveAdditional(container) + + // Save the network PDC + chunkPDC.set(network.namespacedKey, PersistentDataType.TAG_CONTAINER, container) + } + + /** + * Load stored node data from the chunk + * + * @return Whether the data was intact, or up to date + **/ + fun loadData(): Boolean { + val version = networkPDC.getOrDefault(NamespacedKeys.DATA_VERSION, PersistentDataType.INTEGER, 0) + + if (version < network.dataVersion) { + IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained outdated data! It will be rebuilt") + return false + } + + // Deserialize once + val nodeData = networkPDC.getOrDefault(NamespacedKeys.NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).map { + runCatching { TransportNode.load(it, network) }.onFailure { + IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained corrupted data! It will be rebuilt") + it.printStackTrace() + }.getOrElse { + return false + } + } + + nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { + IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} loading node into network!") + it.printStackTrace() + return false + } } + + return true + } + + /** + * Build node data from an unregistered state + **/ + private fun collectAllNodes(): Job = manager.scope.launch { + // Parallel collect the nodes of each section + manager.chunk.sections.map { (y, _) -> + launch { collectSectionNodes(y) } + }.joinAll() + } + + /** + * Collect all nodes in this chunk section + * + * Iterate the section for possible nodes, handle creation + **/ + private suspend fun collectSectionNodes(sectionY: Int) { + val originX = manager.chunk.originX + val originY = sectionY.shl(4) - manager.chunk.inner.world.minHeight + val originZ = manager.chunk.originZ + + for (x: Int in 0..15) { + val realX = originX + x + + for (y: Int in 0..15) { + val realY = originY + y + + for (z: Int in 0..15) { + val realZ = originZ + z + + val snapshot = getBlockSnapshotAsync(manager.chunk.world, realX, realY, realZ) ?: continue + + network.createNodeFromBlock(snapshot) + } + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt new file mode 100644 index 0000000000..b1c74c41e1 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt @@ -0,0 +1,36 @@ +package net.horizonsend.ion.server.features.transport.network.holders + +import kotlinx.coroutines.CoroutineScope +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.World + +interface NetworkHolder { + val network: T + val scope: CoroutineScope + + fun getWorld(): World + + /** + * Builds the transportNetwork + * + * Existing data will be loaded from the chunk's persistent data container, relations between nodes will be built, and any finalization will be performed + **/ + fun handleLoad() + + /** + * Logic for when the holder unloaded + **/ + fun handleUnload() + + /** + * Get a node inside this network + **/ + fun getInternalNode(key: BlockKey): TransportNode? + + /** + * Method used to access nodes inside, and outside the network + **/ + fun getGlobalNode(key: BlockKey): TransportNode? +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt new file mode 100644 index 0000000000..e6861fd4d0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt @@ -0,0 +1,43 @@ +package net.horizonsend.ion.server.features.transport.network.holders + +import kotlinx.coroutines.CoroutineScope +import net.horizonsend.ion.server.features.starship.active.ActiveStarship +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.world.chunk.ChunkRegion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.World +import kotlin.properties.Delegates + +class ShipNetworkHolder(val starship: ActiveStarship) : NetworkHolder { + override var network: T by Delegates.notNull(); private set + + constructor(manager: ActiveStarship, network: (ShipNetworkHolder) -> T) : this(manager) { + this.network = network(this) + } + + override val scope: CoroutineScope = ChunkRegion.scope + + override fun getWorld(): World = starship.world + + override fun handleLoad() { + TODO("Not yet implemented") + } + + override fun handleUnload() { + TODO("Not yet implemented") + } + + override fun getInternalNode(key: BlockKey): TransportNode? { + return network.nodes[key] + } + + override fun getGlobalNode(key: BlockKey): TransportNode? { + // Ship networks cannot access the outside world + return getInternalNode(key) + } + + fun captureNodes() { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index 39046752eb..fbb27c959f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -abstract class NodeFactory(val network: T) { +abstract class NodeFactory(val network: T) { /** * Create and handle placement of a node at the position, if one should be created **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index e623c704c6..5826982fa3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.power.PowerDirectionalNode @@ -29,7 +29,7 @@ enum class NodeType(val clazz: Class) { //ITEM ; - fun newInstance(network: ChunkTransportNetwork): TransportNode { + fun newInstance(network: TransportNetwork): TransportNode { return clazz.getDeclaredConstructor(network::class.java).newInstance(network) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index ce68c4b232..8d0586eb40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.starship.active.ActiveStarship +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -59,18 +60,27 @@ fun getNode(world: World, key: BlockKey, networkType: NetworkType): TransportNod enum class NetworkType { POWER { - override fun get(chunk: IonChunk): ChunkTransportNetwork { - return chunk.transportNetwork.powerNetwork + override fun get(chunk: IonChunk): TransportNetwork { + return chunk.transportNetwork.powerNetwork.network + } + + override fun get(ship: ActiveStarship): TransportNetwork { + TODO("Not yet implemented") } }, GAS { - override fun get(chunk: IonChunk): ChunkTransportNetwork { - return chunk.transportNetwork.powerNetwork + override fun get(chunk: IonChunk): TransportNetwork { + return chunk.transportNetwork.powerNetwork.network + } + + override fun get(ship: ActiveStarship): TransportNetwork { + TODO("Not yet implemented") } }, ; - abstract fun get(chunk: IonChunk): ChunkTransportNetwork + abstract fun get(chunk: IonChunk): TransportNetwork + abstract fun get(ship: ActiveStarship): TransportNetwork } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index a873e367e9..44b236a62e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE @@ -11,13 +11,14 @@ import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import java.util.concurrent.ThreadLocalRandom /** * Represents a single node, or step, in transport transportNetwork **/ interface TransportNode : PDCSerializable { var isDead: Boolean - val network: ChunkTransportNetwork + val network: TransportNetwork override val persistentDataType: Companion get() = Companion /** @@ -64,7 +65,7 @@ interface TransportNode : PDCSerializable> = relationships.filter { // That this node can transfer to the other it.sideOne.transferAllowed && !it.sideTwo.node.isDead - }.map { it.sideTwo.node to it.sideOne.offset } + }.map { it.sideTwo.node to it.sideOne.offset }.shuffled(ThreadLocalRandom.current()) /** * Store additional required data in the serialized container @@ -133,7 +134,7 @@ interface TransportNode : PDCSerializable(network) { +class GasNodeFactory(network: GasNetwork) : NodeFactory(network) { override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 392bcaece3..d8f31fa914 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -4,7 +4,7 @@ import com.manya.pdc.base.EnumDataType import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode @@ -24,8 +24,8 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode, StepHandler { - constructor(network: ChunkPowerNetwork, origin: Long, axis: Axis) : this(network) { +class EndRodNode(override val network: PowerNetwork) : MultiNode, StepHandler { + constructor(network: PowerNetwork, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis } @@ -39,12 +39,12 @@ class EndRodNode(override val network: ChunkPowerNetwork) : MultiNode } - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .firstOrNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index e4a2b93d8a..7eb6bfd8a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -17,12 +17,12 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class InvertedDirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { +class InvertedDirectionalNode(override val network: PowerNetwork) : SingleNode, StepHandler { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + constructor(network: PowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -31,12 +31,12 @@ class InvertedDirectionalNode(override val network: ChunkPowerNetwork) : SingleN return node !is SourceNode<*> } - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index a62790e5fd..bb6257c1f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -19,13 +19,13 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerDirectionalNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { +class PowerDirectionalNode(override val network: PowerNetwork) : SingleNode, StepHandler { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() private var variant: Material by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() - constructor(network: ChunkPowerNetwork, position: BlockKey, variant: Material) : this(network) { + constructor(network: PowerNetwork, position: BlockKey, variant: Material) : this(network) { this.position = position this.variant = variant } @@ -35,12 +35,12 @@ class PowerDirectionalNode(override val network: ChunkPowerNetwork) : SingleNode return node !is SourceNode<*> } - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index f7f1ebb455..a0a21b78b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -20,12 +20,12 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerEqualSplitterNode(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { +class PowerEqualSplitterNode(override val network: PowerNetwork) : SingleNode, StepHandler { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { + constructor(network: PowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -33,11 +33,11 @@ class PowerEqualSplitterNode(override val network: ChunkPowerNetwork) : SingleNo return node !is SourceNode<*> } - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { val transferable = getTransferableNodes() val newHeads = transferable.mapTo(mutableSetOf()) { neighbor -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index dab4e10e8c..2713cbd683 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -24,8 +24,8 @@ import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt import kotlin.properties.Delegates -class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, SourceNode { - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { +class PowerExtractorNode(override val network: PowerNetwork) : SingleNode, SourceNode { + constructor(network: PowerNetwork, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this } @@ -52,17 +52,17 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, /* * Nothing unique with how pathfinding is done, simply move onto a random transferable neighbor that isn't a dead end */ - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { return getTransferableNodes() .filter { it.first.getTransferableNodes().isNotEmpty() } .randomOrNull() } - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { return MoveForward() } - override suspend fun startStep(): Step? { + override suspend fun startStep(): Step? { if (extractableNodes.isEmpty()) return null val extractablePowerPool = extractableNodes.flatMap { it.getPoweredMultiblocks() } @@ -90,7 +90,7 @@ class PowerExtractorNode(override val network: ChunkPowerNetwork) : SingleNode, lastTicked = System.currentTimeMillis() } - override suspend fun getOriginData(): StepOrigin? { + override suspend fun getOriginData(): StepOrigin? { if (getTransferableNodes().isEmpty()) return null return ExtractorPowerOrigin(this) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index ad40b2fcf5..d136023079 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -33,8 +33,8 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, StepHandler { - constructor(network: ChunkPowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { +class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandler { + constructor(network: PowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction } @@ -53,12 +53,12 @@ class PowerFlowMeter(override val network: ChunkPowerNetwork) : SingleNode, Step return node !is SourceNode<*> } - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .randomOrNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 50af83093d..beac55562b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -4,7 +4,9 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.network.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.network.holders.ShipNetworkHolder import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode @@ -24,8 +26,8 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, DestinationNode { - constructor(network: ChunkPowerNetwork, position: BlockKey) : this(network) { +class PowerInputNode(override val network: PowerNetwork) : SingleNode, DestinationNode { + constructor(network: PowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -52,11 +54,20 @@ class PowerInputNode(override val network: ChunkPowerNetwork) : SingleNode, Dest val newZ = z + offset.z val newKey = toBlockKey(newX, newY, newZ) - network.manager.chunk.multiblockManager[newKey] as? PoweredMultiblockEntity + + return@mapNotNull when (val holder = network.holder) { + is ChunkNetworkHolder<*> -> { + holder.manager.chunk.multiblockManager[newKey] as? PoweredMultiblockEntity + } + is ShipNetworkHolder<*> -> { + null //TODO + } + else -> null + } } } - override suspend fun finishChain(head: BranchHead) { + override suspend fun finishChain(head: BranchHead) { val origin = head.holder.getOrigin() head.markDead() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 7fc6d2784c..6c46b5815a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.handleMerges @@ -17,7 +17,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.data.Directional -class PowerNodeFactory(network: ChunkPowerNetwork) : NodeFactory(network) { +class PowerNodeFactory(network: PowerNetwork) : NodeFactory(network) { override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { if (network.nodes.contains(key)) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 3146b67bad..293957d616 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode @@ -43,10 +43,10 @@ import kotlin.math.sin * Represents a solar panel, or multiple **/ class SolarPanelNode( - override val network: ChunkPowerNetwork + override val network: PowerNetwork ) : MultiNode, - SourceNode, - StepHandler { + SourceNode, + StepHandler { override var isDead: Boolean = false override val positions: MutableSet = ConcurrentHashMap.newKeySet() override val relationships: MutableSet = ConcurrentHashMap.newKeySet() @@ -62,7 +62,7 @@ class SolarPanelNode( return node !is PowerExtractorNode } - override suspend fun startStep(): Step? { + override suspend fun startStep(): Step? { val power = getPower() if (power <= 0) return null @@ -79,7 +79,7 @@ class SolarPanelNode( } } - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } @@ -92,7 +92,7 @@ class SolarPanelNode( **/ private var exitDistance: Int = 0 - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { val neighbors = getTransferableNodes() return neighbors.shuffled().firstOrNull { it.first !is SolarPanelNode } ?: neighbors diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 907fcebd18..c6f6096799 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.longs.LongOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode @@ -22,8 +22,8 @@ import org.bukkit.persistence.PersistentDataType * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode, StepHandler { - constructor(network: ChunkPowerNetwork, origin: BlockKey) : this(network) { +class SpongeNode(override val network: PowerNetwork) : MultiNode, StepHandler { + constructor(network: PowerNetwork, origin: BlockKey) : this(network) { positions.add(origin) } @@ -57,12 +57,12 @@ class SpongeNode(override val network: ChunkPowerNetwork) : MultiNode): StepResult { + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { // Simply move on to the next node return MoveForward() } - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .firstOrNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt index ae41475486..472e6579cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.head.BranchHead -interface DestinationNode { +interface DestinationNode { suspend fun finishChain(head: BranchHead) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt index dc4e348ce9..fa5ecf7ee8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.Step import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin * * Nodes may not transfer into a source node **/ -interface SourceNode : StepHandler { +interface SourceNode : StepHandler { suspend fun getOriginData(): StepOrigin? suspend fun startStep(): Step? diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt index 2f234b479b..6fd56d57a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead import net.horizonsend.ion.server.features.transport.step.result.StepResult import org.bukkit.block.BlockFace -interface StepHandler { +interface StepHandler { /** * Handle the stepping of power through this node * diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt index 88116e5727..25ba9a7832 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.step -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin -class Step private constructor( +class Step private constructor( val network: T, private val stepOrigin: StepOrigin, ) : HeadHolder { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt index 9c7d385251..10fe3ec629 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport.step.head -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode -interface BranchHead { +interface BranchHead { val holder: HeadHolder /** Nodes that this head has covered */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt index 96d2fe44f5..37f8162f45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport.step.head -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin -interface HeadHolder { +interface HeadHolder { var head: BranchHead fun getOrigin(): StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt index 96b0df712d..9d49492f23 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt @@ -1,15 +1,15 @@ package net.horizonsend.ion.server.features.transport.step.head -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin import kotlin.properties.Delegates /** A head which branches into multiple sub-heads */ -interface MultiBranchHead : BranchHead { +interface MultiBranchHead : BranchHead { val heads: MutableSet> /** Holder that allows the head within to be replaced */ - class MultiHeadHolder() : HeadHolder { + class MultiHeadHolder() : HeadHolder { override var head: BranchHead by Delegates.notNull() constructor(head: BranchHead) : this() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt index 030d60f769..5eaf92df4a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt @@ -1,13 +1,13 @@ package net.horizonsend.ion.server.features.transport.step.head -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import org.bukkit.block.BlockFace /** * Can either branch off of a MultiBranch or exist alone **/ -interface SingleBranchHead : BranchHead { +interface SingleBranchHead : BranchHead { /** The last offset this branch moved */ var lastDirection: BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt index 25537e59b0..c16567ec77 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.step.head.gas -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead @@ -10,9 +10,9 @@ import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead * **/ class MultiGasBranchHead( - override val holder: HeadHolder, + override val holder: HeadHolder, override val share: Double, override val previousNodes: MutableSet = mutableSetOf(), - override val heads: MutableSet> = mutableSetOf(), -) : MultiBranchHead, GasBranchHead + override val heads: MutableSet> = mutableSetOf(), +) : MultiBranchHead, GasBranchHead diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt index d079928670..7e814d0ab4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.step.head.gas -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork as ChunkTransportNetwork1 -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork as ChunkTransportNetwork1 +import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler @@ -16,12 +16,12 @@ import org.bukkit.block.BlockFace * **/ class SingleGasBranchHead( - override val holder: HeadHolder, + override val holder: HeadHolder, override var lastDirection: BlockFace, override var currentNode: TransportNode, override val share: Double, override val previousNodes: MutableSet = mutableSetOf() -) : SingleBranchHead, GasBranchHead { +) : SingleBranchHead, GasBranchHead { private var isDead = false override fun markDead() { @@ -34,14 +34,14 @@ class SingleGasBranchHead( override suspend fun stepForward() { val node = currentNode - if (tryCast>(node) { finishChain(this@SingleGasBranchHead) }) return + if (tryCast>(node) { finishChain(this@SingleGasBranchHead) }) return // All other nodes handle steps transferring in / out node as StepHandler - val result = node.handleHeadStep(this as SingleBranchHead) + val result = node.handleHeadStep(this as SingleBranchHead) - result.apply(holder as HeadHolder) + result.apply(holder as HeadHolder) } // Get around runtime type erasure diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt index db24d40f4d..946ac1280b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.step.head.power -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.step.head.HeadHolder import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead @@ -10,9 +10,9 @@ import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead * **/ class MultiPowerBranchHead( - override val holder: HeadHolder, + override val holder: HeadHolder, override val share: Double, override val previousNodes: MutableSet = mutableSetOf(), - override val heads: MutableSet> = mutableSetOf(), -) : MultiBranchHead, PowerBranchHead + override val heads: MutableSet> = mutableSetOf(), +) : MultiBranchHead, PowerBranchHead diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt index b4221cadec..ceae3a6116 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.step.head.power -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork as ChunkTransportNetwork1 -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork as ChunkTransportNetwork1 +import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler @@ -16,12 +16,12 @@ import org.bukkit.block.BlockFace * **/ class SinglePowerBranchHead( - override val holder: HeadHolder, + override val holder: HeadHolder, override var lastDirection: BlockFace, override var currentNode: TransportNode, override val share: Double, override val previousNodes: MutableSet = mutableSetOf() -) : SingleBranchHead, PowerBranchHead { +) : SingleBranchHead, PowerBranchHead { private var isDead = false override fun markDead() { @@ -34,14 +34,14 @@ class SinglePowerBranchHead( override suspend fun stepForward() { val node = currentNode - if (tryCast>(node) { finishChain(this@SinglePowerBranchHead) }) return + if (tryCast>(node) { finishChain(this@SinglePowerBranchHead) }) return // All other nodes handle steps transferring in / out node as StepHandler - val result = node.handleHeadStep(this as SingleBranchHead) + val result = node.handleHeadStep(this as SingleBranchHead) - result.apply(holder as HeadHolder) + result.apply(holder as HeadHolder) } // Get around runtime type erasure diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt index 8183393f0c..098eef4dc1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.step.origin -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork -interface StepOrigin +interface StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt index 15cacc8269..0c46763489 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport.step.origin.gas -import net.horizonsend.ion.server.features.transport.network.ChunkGasNetwork +import net.horizonsend.ion.server.features.transport.network.GasNetwork import net.horizonsend.ion.server.features.transport.node.gas.GasExtractorNode import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class ExtractedGasOrigin( val extractorNode: GasExtractorNode -) : StepOrigin +) : StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt index aa696a49e0..bde2dfc276 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt @@ -2,13 +2,13 @@ package net.horizonsend.ion.server.features.transport.step.origin.power import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class ExtractorPowerOrigin( val extractorNode: PowerExtractorNode -) : StepOrigin, PowerOrigin { +) : StepOrigin, PowerOrigin { override val transferLimit: Int = extractorNode.getTransferPower() /** * Remove power from the origin extractor's multiblocks. diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt index 138f620356..fe330e016c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.step.origin.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.network.ChunkPowerNetwork +import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin -class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin, PowerOrigin { +class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin, PowerOrigin { override val transferLimit: Int = Int.MAX_VALUE private val powerTransfer = origin.tickAndGetPower() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt index d92846af53..2de3cceec0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.step.result -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.features.transport.step.head.HeadHolder /** A result which changes the head of the step to a new one */ -class ChangeHead(val new: BranchHead) : StepResult { +class ChangeHead(val new: BranchHead) : StepResult { override suspend fun apply(headHolder: HeadHolder) { headHolder.head = new } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt index dacd5f1f58..6fd6f9804a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.transport.step.result -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.head.HeadHolder /** A result which marks the branch as dead */ -class EndBranch : StepResult { +class EndBranch : StepResult { override suspend fun apply(headHolder: HeadHolder) { headHolder.head.markDead() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt index 46a9e08a7b..1534339d9a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.step.result -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.SourceNode import net.horizonsend.ion.server.features.transport.node.type.StepHandler @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead /** A result which moves the head of the branch forward, using the current node's pathfinding */ -class MoveForward() : StepResult { +class MoveForward() : StepResult { override suspend fun apply(headHolder: HeadHolder) { val branchHead = headHolder.head diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt index 8d851d2abc..f8883b5ab1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport.step.result -import net.horizonsend.ion.server.features.transport.network.ChunkTransportNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -interface StepResult { +interface StepResult { suspend fun apply(headHolder: HeadHolder) } From c3a06a1e435832bd7a5761b6a8338d4f7cc3cc22 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 20 Jul 2024 13:19:27 -0500 Subject: [PATCH 097/500] add network holders to ships --- .../network/holders/ShipNetworkHolder.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt index e6861fd4d0..bae53a3a1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt @@ -21,11 +21,12 @@ class ShipNetworkHolder(val starship: ActiveStarship) : Net override fun getWorld(): World = starship.world override fun handleLoad() { - TODO("Not yet implemented") + captureNodes() } override fun handleUnload() { - TODO("Not yet implemented") + network.clearData() + rebuildStaticNetwork() } override fun getInternalNode(key: BlockKey): TransportNode? { @@ -37,7 +38,17 @@ class ShipNetworkHolder(val starship: ActiveStarship) : Net return getInternalNode(key) } + /** + * Build the transport network from the starship blocks + **/ fun captureNodes() { } + + /** + * Rebuild the base networks in the chunks the ship occupies when it is released + **/ + fun rebuildStaticNetwork() { + + } } From 1d1f8d8ead26c324541f7e29bc465913479359b7 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 30 Jul 2024 00:52:08 -0500 Subject: [PATCH 098/500] shape aliases --- .../server/command/misc/MultiblockCommand.kt | 6 +- .../multiblock/shape/BlockRequirement.kt | 1 + .../multiblock/shape/MultiblockShape.kt | 63 +++++++++++-------- .../type/autocrafter/AutoCrafterMultiblock.kt | 2 +- .../multiblock/type/misc/AirlockMultiblock.kt | 4 +- .../type/printer/ArmorPrinterMultiblock.kt | 2 +- .../type/printer/CarbonPrinterMultiblock.kt | 2 +- 7 files changed, 49 insertions(+), 31 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index fd5babd149..432ba1ddee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -55,6 +55,10 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { val possibleTiers = Multiblocks.all().filter { it.name == multiblockType } + if (possibleTiers.size == 1) { + onCheck(player, possibleTiers.first(), sign.x, sign.y, sign.z) + } + val message = Component.text() .append(Component.text("Which type of $multiblockType are you trying to build? (Click one)")) .append(Component.newline()) @@ -102,7 +106,7 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { sendEntityPacket(sender, displayBlock(sender.world.minecraft, expected, Vector(xx, yy, zz), 0.5f, true), 10 * 20L) sender.userError( - "Block at ${Vec3i(relative.location)} doesn't match! Expected ${expected.material}, found ${relative.type}." + "Block at ${Vec3i(relative.location)} doesn't match! Expected ${requirement.alias}, found ${relative.type}." ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 6a2a60e931..2aa9d4b244 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -5,6 +5,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData class BlockRequirement( + val alias: String, var example: BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 03604e9bae..d12263b6c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -264,6 +264,7 @@ class MultiblockShape { fun type(type: Material) { val requirement = BlockRequirement( + alias = type.toString(), example = type.createBlockData(), syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type } @@ -272,10 +273,11 @@ class MultiblockShape { complete(requirement) } - fun anyType(vararg types: Material, edit: BlockRequirement.() -> Unit = {}) { + fun anyType(vararg types: Material, alias: String, edit: BlockRequirement.() -> Unit = {}) { val typeSet = EnumSet.copyOf(types.toList()) val requirement = BlockRequirement( + alias = alias, example = types.first().createBlockData(), syncCheck = { block, _, loadChunks -> typeSet.contains(if (loadChunks) block.type else block.getTypeSafe()) @@ -294,6 +296,7 @@ class MultiblockShape { fun customBlock(customBlock: CustomBlock) { val requirement = BlockRequirement( + alias = customBlock.identifier, example = customBlock.blockData, syncCheck = { block, _, loadChunks -> if (loadChunks) CustomBlocks.getByBlock(block) else { @@ -308,14 +311,18 @@ class MultiblockShape { complete(requirement) } - fun anyType(types: Iterable, edit: BlockRequirement.() -> Unit = {}) = anyType(*types.toList().toTypedArray(), edit = edit) + fun anyType(alias: String, types: Iterable, edit: BlockRequirement.() -> Unit = {}) = anyType( + *types.toList().toTypedArray(), + alias = alias, + edit = edit + ) - fun filteredTypes(filter: (Material) -> Boolean) = anyType(MATERIALS.filter(filter)) + fun filteredTypes(alias: String, filter: (Material) -> Boolean) = anyType(alias, MATERIALS.filter(filter)) - fun carbyne() = anyType(CONCRETE_TYPES) { setExample(Material.GRAY_CONCRETE.createBlockData()) } + fun carbyne() = anyType("any concrete", CONCRETE_TYPES) { setExample(Material.GRAY_CONCRETE.createBlockData()) } - fun terracotta() = anyType(TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } - fun stainedTerracotta() = anyType(STAINED_TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } + fun terracotta() = anyType("any terracotta", TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } + fun stainedTerracotta() = anyType("any stained terracotta", STAINED_TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } fun glass() = type(Material.GLASS) fun anvil() = type(Material.ANVIL) @@ -324,22 +331,23 @@ class MultiblockShape { fun cruiserReactorCore() = customBlock(CRUISER_REACTOR_CORE) fun netheriteCasing() = customBlock(NETHERITE_CASING) fun enrichedUraniumBlock() = customBlock(ENRICHED_URANIUM_BLOCK) - fun stainedGlass() = filteredTypes { it.isStainedGlass } - fun anyGlass() = filteredTypes { it.isGlass } + fun stainedGlass() = filteredTypes("any stained glass block") { it.isStainedGlass } + fun anyGlass() = filteredTypes("any glass block") { it.isGlass } fun seaLantern() = type(Material.SEA_LANTERN) fun glassPane() = type(Material.GLASS_PANE) - fun stainedGlassPane() = filteredTypes { it.isStainedGlassPane } - fun anyGlassPane() = filteredTypes { it.isGlassPane } + fun stainedGlassPane() = filteredTypes("any stained glass pane") { it.isStainedGlassPane } + fun anyGlassPane() = filteredTypes("any stained glass") { it.isGlassPane } - fun anyStairs() = filteredTypes { it.isStairs } + fun anyStairs() = filteredTypes("any stair block") { it.isStairs } - fun anyWall() = filteredTypes { it.isWall } + fun anyWall() = filteredTypes("any wall block") { it.isWall } - fun anyWool() = filteredTypes { it.isWool } + fun anyWool() = filteredTypes("any wool block") { it.isWool } - fun anySlab() = filteredTypes { it.isSlab } + fun anySlab() = filteredTypes("any slab block") { it.isSlab } fun anyDoubleSlab() = complete( BlockRequirement( + alias = "any double slab block", example = Material.STONE_BRICK_SLAB.createBlockData().apply { this as Slab this.type = Slab.Type.DOUBLE @@ -359,6 +367,7 @@ class MultiblockShape { fun terracottaOrDoubleslab() { BlockRequirement( + alias = "any double slab or terracotta block", example = Material.TERRACOTTA.createBlockData(), syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) @@ -376,7 +385,7 @@ class MultiblockShape { ) } - fun concrete() = filteredTypes { it.isConcrete } + fun concrete() = filteredTypes("any concrete block") { it.isConcrete } fun sculkCatalyst() = type(Material.SCULK_CATALYST) fun stoneBrick() = type(Material.STONE_BRICKS) @@ -404,7 +413,8 @@ class MultiblockShape { Material.WAXED_CUT_COPPER, Material.WAXED_EXPOSED_CUT_COPPER, Material.WAXED_WEATHERED_CUT_COPPER, - Material.WAXED_OXIDIZED_CUT_COPPER + Material.WAXED_OXIDIZED_CUT_COPPER, + alias = "any copper block", ) fun titaniumBlock() = customBlock(CustomBlocks.TITANIUM_BLOCK) @@ -413,25 +423,25 @@ class MultiblockShape { fun steelBlock() = customBlock(CustomBlocks.STEEL_BLOCK) fun wireInputComputer() = type(Wires.INPUT_COMPUTER_BLOCK) - fun redstoneLamp() = filteredTypes { it.isRedstoneLamp } + fun redstoneLamp() = filteredTypes("redstone lamp") { it.isRedstoneLamp } - fun daylightSensor() = filteredTypes { it.isDaylightSensor } + fun daylightSensor() = filteredTypes("daylight sensor") { it.isDaylightSensor } fun craftingTable() = type(Material.CRAFTING_TABLE) fun extractor() = type(Extractors.EXTRACTOR_BLOCK) fun glowstone() = type(Material.GLOWSTONE) - fun sponge() = anyType(Material.SPONGE, Material.WET_SPONGE) + fun sponge() = anyType(Material.SPONGE, Material.WET_SPONGE, alias = "sponge") fun endRod() = type(Material.END_ROD) fun grindstone() = type(Material.GRINDSTONE) fun hopper() = type(Material.HOPPER) - fun anyDoor() = filteredTypes { it.isDoor } - fun anyButton() = filteredTypes { it.isButton } + fun anyDoor() = filteredTypes("any door") { it.isDoor } + fun anyButton() = filteredTypes("any button") { it.isButton } - fun anyPipedInventory() = filteredTypes { Pipes.isPipedInventory(it) } + fun anyPipedInventory() = filteredTypes("any container block") { Pipes.isPipedInventory(it) } fun pistonBase() = type(Material.PISTON) fun pistonHead() = type(Material.PISTON_HEAD) @@ -440,8 +450,8 @@ class MultiblockShape { fun dispenser() = type(Material.DISPENSER) fun lodestone() = type(Material.LODESTONE) fun noteBlock() = type(Material.NOTE_BLOCK) - fun anyTrapdoor() = filteredTypes { it.isTrapdoor } - fun anyFroglight() = filteredTypes { it.isFroglight } + fun anyTrapdoor() = filteredTypes("any trapdoor") { it.isTrapdoor } + fun anyFroglight() = filteredTypes("any froglight") { it.isFroglight } fun thrusterBlock() = anyType( Material.OCHRE_FROGLIGHT, @@ -450,12 +460,14 @@ class MultiblockShape { Material.GLOWSTONE, Material.REDSTONE_LAMP, Material.MAGMA_BLOCK, - Material.SEA_LANTERN + Material.SEA_LANTERN, + alias = "any light block" ) fun lightningRod() = type(Material.LIGHTNING_ROD) fun machineFurnace() = complete(BlockRequirement( + alias = "furnace", example = Material.FURNACE.createBlockData(), syncCheck = check@{ block, inward, loadChunks -> val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockSateSafe(block.world, block.x, block.y, block.z) ?: return@check false @@ -505,6 +517,7 @@ class MultiblockShape { Material.SMOOTH_QUARTZ, Material.QUARTZ_BRICKS, Material.QUARTZ_BLOCK, + alias = "stone bricks" ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 6831eadb3f..7ea6acf8e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -67,7 +67,7 @@ abstract class AutoCrafterMultiblock( y(+0) { x(-2).anyPipedInventory() x(-1).endRod() - x(+0).anyType(Material.DISPENSER, Material.DROPPER) + x(+0).anyType(Material.DISPENSER, Material.DROPPER, alias= "dispenser or dropper") x(+1).endRod() x(+2).anyPipedInventory() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt index 22c6a36872..f9d75a6a25 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AirlockMultiblock.kt @@ -37,11 +37,11 @@ object AirlockMultiblock : Multiblock(), InteractableMultiblock { } y(-1) { - x(xOffset + 0).anyType(Material.IRON_BARS, Material.NETHER_PORTAL) + x(xOffset + 0).anyType(Material.IRON_BARS, Material.NETHER_PORTAL, alias = "iron bars") } y(+0) { - x(xOffset + 0).anyType(Material.IRON_BARS, Material.NETHER_PORTAL) + x(xOffset + 0).anyType(Material.IRON_BARS, Material.NETHER_PORTAL, alias = "iron bars") } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt index a948e80849..c9858a817c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/ArmorPrinterMultiblock.kt @@ -18,7 +18,7 @@ abstract class AbstractArmorPrinterMultiblock : PrinterMultiblock() { override fun MultiblockShape.RequirementBuilder.printerMachineryBlock() = sponge() override fun MultiblockShape.RequirementBuilder.printerCoreBlock() = type(Material.ANVIL) override fun MultiblockShape.RequirementBuilder.printerProductBlock() = - filteredTypes { it == Material.TERRACOTTA || it.isStainedTerracotta } + filteredTypes("any terracotta") { it == Material.TERRACOTTA || it.isStainedTerracotta } } object ArmorPrinterMultiblock : AbstractArmorPrinterMultiblock() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt index fc34401672..4b4149891f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonPrinterMultiblock.kt @@ -16,7 +16,7 @@ abstract class AbstractCarbonPrinterMultiblock : PrinterMultiblock() { override fun MultiblockShape.RequirementBuilder.printerMachineryBlock() = sponge() override fun MultiblockShape.RequirementBuilder.printerCoreBlock() = type(Material.MAGMA_BLOCK) - override fun MultiblockShape.RequirementBuilder.printerProductBlock() = filteredTypes { it.isConcretePowder } + override fun MultiblockShape.RequirementBuilder.printerProductBlock() = filteredTypes("any concrete powder") { it.isConcretePowder } } object CarbonPrinterMultiblock : AbstractCarbonPrinterMultiblock() { From 102bf5d493fef146936095062beb6f73db4e32e4 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 31 Jul 2024 06:57:46 -0500 Subject: [PATCH 099/500] some gas nodes --- .../transport/node/gas/GasJunctionNode.kt | 15 ++++ .../transport/node/gas/GasNodeFactory.kt | 59 +++++++++++++ .../transport/node/gas/LightningRodNode.kt | 21 ++++- .../transport/node/gas/PowerJunctionNode.kt | 4 - .../transport/node/general/JunctionNode.kt | 71 ++++++++++++++++ .../transport/node/general/LinearNode.kt | 82 +++++++++++++++++++ .../transport/node/power/EndRodNode.kt | 80 ++---------------- .../transport/node/power/SpongeNode.kt | 66 +-------------- 8 files changed, 259 insertions(+), 139 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt new file mode 100644 index 0000000000..17456593ec --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.transport.node.gas + +import net.horizonsend.ion.server.features.transport.network.GasNetwork +import net.horizonsend.ion.server.features.transport.node.general.JunctionNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +class GasJunctionNode(network: GasNetwork) : JunctionNode(network) { + constructor(network: GasNetwork, origin: BlockKey) : this(network) { + positions.add(origin) + } + + override suspend fun addBack(position: BlockKey) { + network.nodeFactory.addJunction(position, handleRelationships = false) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt index cfc922973c..f6c557247a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt @@ -3,10 +3,69 @@ package net.horizonsend.ion.server.features.transport.node.gas import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.transport.network.GasNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory +import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.handleMerges +import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.faces +import org.bukkit.Material +import org.bukkit.block.data.Directional class GasNodeFactory(network: GasNetwork) : NodeFactory(network) { override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { + if (network.nodes.contains(key)) return + when { + // Straight wires + snapshot.type == Material.END_ROD -> addLightningRod(snapshot.data as Directional, key) + + // Omnidirectional wires + snapshot.type == Material.SPONGE -> addJunction(key) + } + } + + suspend fun addLightningRod(data: Directional, position: Long, handleRelationships: Boolean = true) { + val axis = data.facing.axis + + // The neighbors in the direction of the wire's facing, that are also facing that direction + val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()) + .values + .filterIsInstance() + .filterTo(mutableListOf()) { it.axis == axis } + + val finalNode = when (neighbors.size) { + // Disconnected + 0 -> LightningRodNode(network, position, data.facing.axis).apply { loadIntoNetwork() } + + // Consolidate into neighbor + 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") + + // Should be a max of 2 + 2 -> handleMerges(neighbors).addPosition(position) + + else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") + } + + if (handleRelationships) finalNode.rebuildRelations() + } + + suspend fun addJunction(position: BlockKey, handleRelationships: Boolean = true) { + val neighbors = getNeighborNodes(position, network.nodes).values.filterIsInstanceTo>(mutableListOf()) + + val finalNode = when (neighbors.size) { + // New sponge node + 0 -> GasJunctionNode(network, position).apply { loadIntoNetwork() } + + // Consolidate into neighbor + 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") + + // Join multiple neighbors together + in 2..6 -> handleMerges(neighbors).addPosition(position) + + else -> throw NotImplementedError() + } + + if (handleRelationships) finalNode.rebuildRelations() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt index 7e5d7465b1..890dd61b2f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt @@ -1,4 +1,23 @@ package net.horizonsend.ion.server.features.transport.node.gas -class LightningRodNode { +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.network.GasNetwork +import net.horizonsend.ion.server.features.transport.node.general.LinearNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Axis +import org.bukkit.block.data.Directional + +class LightningRodNode(network: GasNetwork) : LinearNode(network) { + constructor(network: GasNetwork, origin: Long, axis: Axis) : this(network) { + positions.add(origin) + this.axis = axis + } + + override suspend fun addBack(position: BlockKey) { + network.nodeFactory.addLightningRod( + getBlockSnapshotAsync(network.world, position)!!.data as Directional, + position, + handleRelationships = false + ) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt deleted file mode 100644 index b6a5a22ec3..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/PowerJunctionNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class PowerJunctionNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt new file mode 100644 index 0000000000..2aca88eea0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -0,0 +1,71 @@ +package net.horizonsend.ion.server.features.transport.node.general + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +abstract class JunctionNode, B: JunctionNode>(override val network: T) : MultiNode, StepHandler { + override var isDead: Boolean = false + override val positions: MutableSet = LongOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() + + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is SourceNode<*> + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) + } + + abstract suspend fun addBack(position: BlockKey) + + override suspend fun rebuildNode(position: BlockKey) { + // Create new nodes, automatically merging together + positions.forEach { + // Do not handle relations + addBack(it) + } + + // Handle relations once fully rebuilt + positions.forEach { + network.nodes[it]?.buildRelations(it) + } + } + + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + // Simply move on to the next node + return MoveForward() + } + + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } + .firstOrNull() + +// override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" + + override fun toString(): String { + return """ + [Gas Junction Node] + ${positions.size} positions + Relationships: ${relationships.joinToString { it.sideTwo.toString() }} + """.trimIndent() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt new file mode 100644 index 0000000000..cfc34b79bd --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -0,0 +1,82 @@ +package net.horizonsend.ion.server.features.transport.node.general + +import com.manya.pdc.base.EnumDataType +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.SourceNode +import net.horizonsend.ion.server.features.transport.node.type.StepHandler +import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead +import net.horizonsend.ion.server.features.transport.step.result.MoveForward +import net.horizonsend.ion.server.features.transport.step.result.StepResult +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.faces +import org.bukkit.Axis +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.properties.Delegates + +abstract class LinearNode, B: LinearNode>(override val network: T) : MultiNode, StepHandler { + override var isDead: Boolean = false + override val positions: MutableSet = LongOpenHashSet() + override val relationships: MutableSet = ObjectOpenHashSet() + var axis by Delegates.notNull() + + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is SourceNode<*> + } + + override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { + // Simply move on to the next node + return MoveForward() + } + + override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() + .filterNot { head.previousNodes.contains(it.first) } + .firstOrNull() + + abstract suspend fun addBack(position: BlockKey) + + override suspend fun rebuildNode(position: BlockKey) { + // Create new nodes, automatically merging together + positions.forEach { + addBack(it) + } + + // Handle relations once fully rebuilt + positions.forEach { + network.nodes[it]?.buildRelations(it) + } + } + + override suspend fun buildRelations(position: BlockKey) { + for (offset in axis.faces.toList()) { + val offsetKey = getRelative(position, offset, 1) + val neighborNode = network.getNode(offsetKey) ?: continue + + if (this == neighborNode) continue + + addRelationship(neighborNode, offset) + } + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) + coveredPositions?.let { positions.addAll(it.asIterable()) } + + axis = persistentDataContainer.getOrDefault(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), Axis.Y) + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) + persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), axis) + } + + override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index d8f31fa914..f4fd647b11 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -1,87 +1,23 @@ package net.horizonsend.ion.server.features.transport.node.power -import com.manya.pdc.base.EnumDataType -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Axis -import org.bukkit.block.BlockFace import org.bukkit.block.data.Directional -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates -class EndRodNode(override val network: PowerNetwork) : MultiNode, StepHandler { +class EndRodNode(network: PowerNetwork) : LinearNode(network) { constructor(network: PowerNetwork, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis } - override var isDead: Boolean = false - override val positions: MutableSet = LongOpenHashSet() - override val relationships: MutableSet = ObjectOpenHashSet() - var axis by Delegates.notNull() - - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> - } - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() + override suspend fun addBack(position: BlockKey) { + network.nodeFactory.addEndRod( + getBlockSnapshotAsync(network.world, position)!!.data as Directional, + position, + handleRelationships = false + ) } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .firstOrNull() - - override suspend fun rebuildNode(position: BlockKey) { - // Create new nodes, automatically merging together - positions.forEach { - network.nodeFactory.addEndRod(getBlockSnapshotAsync(network.world, it)!!.data as Directional, it, handleRelationships = false) - } - - // Handle relations once fully rebuilt - positions.forEach { - network.nodes[it]?.buildRelations(it) - } - } - - override suspend fun buildRelations(position: BlockKey) { - for (offset in axis.faces.toList()) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.getNode(offsetKey) ?: continue - - if (this == neighborNode) continue - - addRelationship(neighborNode, offset) - } - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - - axis = persistentDataContainer.getOrDefault(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), Axis.Y) - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) - persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), axis) - } - - override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index c6f6096799..76778b8bbf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -1,78 +1,20 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType /** * Represents a sponge [omnidirectional pipe] * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(override val network: PowerNetwork) : MultiNode, StepHandler { +class SpongeNode(network: PowerNetwork) : JunctionNode(network) { constructor(network: PowerNetwork, origin: BlockKey) : this(network) { positions.add(origin) } - override var isDead: Boolean = false - override val positions: MutableSet = LongOpenHashSet() - override val relationships: MutableSet = ObjectOpenHashSet() - - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) - } - - override suspend fun rebuildNode(position: BlockKey) { - // Create new nodes, automatically merging together - positions.forEach { - // Do not handle relations - network.nodeFactory.addSponge(it, handleRelationships = false) - } - - // Handle relations once fully rebuilt - positions.forEach { - network.nodes[it]?.buildRelations(it) - } - } - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .firstOrNull() - -// override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" - - override fun toString(): String { - return """ - [Sponge Node] - ${positions.size} positions - Relationships: ${relationships.joinToString { it.sideTwo.toString() }} - """.trimIndent() + override suspend fun addBack(position: BlockKey) { + network.nodeFactory.addSponge(position, handleRelationships = false) } } From e6974183be8fb53fa48e8022f2b84d4e624613b0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 11 Aug 2024 13:57:16 -0500 Subject: [PATCH 100/500] start on new gas collection system --- .../horizonsend/ion/server/features/multiblock/Multiblocks.kt | 2 +- .../starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt | 4 ++-- .../kotlin/net/horizonsend/ion/server/features/space/Space.kt | 2 -- .../ion/server/features/starship/active/SubsystemDetector.kt | 2 +- .../subsystem/weapon/secondary/AIPhaserWeaponSystem.kt | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 90ec2101c2..1426161149 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -254,7 +254,7 @@ object Multiblocks : IonServerComponent() { registerMultiblock(PulseCannonStarshipWeaponMultiblock) registerMultiblock(HeavyLaserStarshipWeaponMultiblock) registerMultiblock(AIHeavyLaserStarshipWeaponMultiblock) - registerMultiblock(AIPhaserStarshipWeaponMultiblocK) + registerMultiblock(AIPhaserStarshipWeaponMultiblock) registerMultiblock(TorpedoStarshipWeaponMultiblock) registerMultiblock(PointDefenseStarshipWeaponMultiblockTop) registerMultiblock(PointDefenseStarshipWeaponMultiblockSide) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt index 34a9e4ef04..50e02e30c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.AIPhaserWeaponSystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt index 74df96ee02..94e2794b8f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt @@ -17,8 +17,6 @@ import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet import net.horizonsend.ion.server.features.space.body.planet.CachedRoguePlanet import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.isWater import net.horizonsend.ion.server.miscellaneous.utils.listen import net.horizonsend.ion.server.miscellaneous.utils.optional diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index 4c9cda2ba4..c6c76f32a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.features.multiblock.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock @@ -14,6 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultibloc import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIPhaserWeaponSystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIPhaserWeaponSystem.kt index c3ea365563..2ccb02459d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIPhaserWeaponSystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/AIPhaserWeaponSystem.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.PhaserProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace From 20690cc3c8d8f0f85b7228b99d19c52319581e65 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 26 Aug 2024 23:47:06 -0500 Subject: [PATCH 101/500] dont inherit reward config --- .../ion/server/features/ai/reward/AICreditRewardProvider.kt | 2 +- .../ion/server/features/ai/reward/AIItemRewardProvider.kt | 2 +- .../ion/server/features/ai/reward/AIRewardsProvider.kt | 2 -- .../ion/server/features/ai/reward/AIXPRewardProvider.kt | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AICreditRewardProvider.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AICreditRewardProvider.kt index 181fb9ff2c..1166873a3d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AICreditRewardProvider.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AICreditRewardProvider.kt @@ -12,7 +12,7 @@ import org.slf4j.Logger import org.slf4j.LoggerFactory import java.util.concurrent.atomic.AtomicInteger -open class AICreditRewardProvider(override val starship: ActiveStarship, override val configuration: AITemplate.CreditRewardProviderConfiguration) : AIRewardsProvider { +open class AICreditRewardProvider(override val starship: ActiveStarship, val configuration: AITemplate.CreditRewardProviderConfiguration) : AIRewardsProvider { override val log: Logger = LoggerFactory.getLogger(javaClass) override fun processDamagerRewards(damager: PlayerDamager, points: AtomicInteger, pointsSum: Int) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIItemRewardProvider.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIItemRewardProvider.kt index 8aa1235ee3..514df8e4e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIItemRewardProvider.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIItemRewardProvider.kt @@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory class AIItemRewardProvider( override val starship: ActiveControlledStarship, - override val configuration: AITemplate.ItemRewardProviderConfiguration + val configuration: AITemplate.ItemRewardProviderConfiguration ) : AIRewardsProvider { override val log: Logger = LoggerFactory.getLogger(javaClass) val items = configuration.items.associate { (string, count, percent) -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIRewardsProvider.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIRewardsProvider.kt index 470a03d980..57d5828c22 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIRewardsProvider.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIRewardsProvider.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.ai.reward -import net.horizonsend.ion.server.features.ai.configuration.AITemplate import net.horizonsend.ion.server.features.progression.ShipKillXP import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement @@ -11,7 +10,6 @@ import org.slf4j.Logger import java.util.concurrent.atomic.AtomicInteger interface AIRewardsProvider : RewardsProvider { - val configuration: AITemplate.AIRewardsProviderConfiguration val starship: ActiveStarship val log: Logger diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIXPRewardProvider.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIXPRewardProvider.kt index 1469ae457f..29ffb3bf79 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIXPRewardProvider.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/reward/AIXPRewardProvider.kt @@ -12,7 +12,7 @@ import java.util.concurrent.atomic.AtomicInteger import kotlin.math.pow import kotlin.math.sqrt -class AIXPRewardProvider(override val starship: ActiveStarship, override val configuration: AITemplate.SLXPRewardProviderConfiguration) : AIRewardsProvider { +class AIXPRewardProvider(override val starship: ActiveStarship, val configuration: AITemplate.SLXPRewardProviderConfiguration) : AIRewardsProvider { override val log: Logger = LoggerFactory.getLogger(javaClass) override fun processDamagerRewards(damager: PlayerDamager, points: AtomicInteger, pointsSum: Int) { From de30f203a6804fe516bea7507b7b7c36c17240d2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 26 Aug 2024 23:47:06 -0500 Subject: [PATCH 102/500] packaged multiblocks --- .../server/command/admin/ItemDebugCommand.kt | 11 ++ .../server/features/multiblock/PrePackaged.kt | 125 ++++++++++++++++++ .../multiblock/shape/MultiblockShape.kt | 14 +- .../persistence/NamespacedKeys.kt | 2 + 4 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt index 9b13ea6b5d..58b8e0e739 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt @@ -17,6 +17,8 @@ import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModif import net.horizonsend.ion.server.features.custom.items.util.serialization.CustomItemSerialization import net.horizonsend.ion.server.features.gui.GuiItems import net.horizonsend.ion.server.miscellaneous.utils.text.itemName +import net.horizonsend.ion.server.features.multiblock.Multiblock +import org.bukkit.command.CommandSender import org.bukkit.Material import org.bukkit.entity.Player import org.bukkit.event.inventory.ClickType @@ -94,6 +96,15 @@ object ItemDebugCommand : SLCommand() { sender.information("Removed power to $amount") } + @Subcommand("give prepackaged") + @CommandCompletion("@multiblocks") + fun onGivePrepackaged(sender: CommandSender, prePackagedType: Multiblock, recipient: Player?) { + val destination: Player = recipient ?: (sender as? Player ?: fail { "You must specify a player!" }) + + destination.inventory.addItem(PackagedMultiblockItem.constructFor(prePackagedType)) + sender.information("Added to inventory") + } + @Subcommand("test all") fun onTestAll(sender: Player) { val allItems = CustomItemRegistry.ALL.map { item -> object : GuiItems.AbstractButtonItem(item.displayName.itemName, item.constructItemStack()) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt new file mode 100644 index 0000000000..cf79873470 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -0,0 +1,125 @@ +package net.horizonsend.ion.server.features.multiblock + +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded +import net.kyori.adventure.text.Component.text +import org.bukkit.Material +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Directional +import org.bukkit.block.sign.Side +import org.bukkit.entity.Player +import org.bukkit.event.block.BlockPlaceEvent +import org.bukkit.inventory.EquipmentSlot +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +object PrePackaged { + fun getOriginFromPlacement(clickedBlock: Block, direction: BlockFace, shape: MultiblockShape): Block { + val requirements = shape.getRequirementMap(direction) + val minY = requirements.entries.minOfOrNull { it.key.y } ?: throw NullPointerException("Multiblock has no shape!") + + return clickedBlock + .getRelative(BlockFace.UP, 1) // Get the block on top of the clicked block + .getRelative(BlockFace.DOWN, minY) // Go up (down negative blocks) until the origin is high enough to fit the blocks below it + } + + fun checkObstructions(origin: Block, direction: BlockFace, shape: MultiblockShape): List { + val requirements = shape.getRequirementMap(direction) + val obstructed = mutableListOf() + + for ((offset, _) in requirements) { + val offsetBlock = origin.getRelativeIfLoaded(offset.x, offset.y, offset.z) + + if (offsetBlock == null) { + obstructed.add(Vec3i(origin.x, origin.y, origin.z).plus(offset)) + continue + } + + if (!offsetBlock.type.isAir) { + obstructed.add(Vec3i(origin.x, origin.y, origin.z).plus(offset)) + } + } + + val signPosition = origin.getRelative(direction.oppositeFace, 1) + if (!signPosition.type.isAir) { + obstructed.add(Vec3i(signPosition.x, signPosition.y, signPosition.z)) + } + + return obstructed + } + + fun place(player: Player, origin: Block, direction: BlockFace, data: PackagedMultiblockData) { + val requirements = data.multiblock.shape.getRequirementMap(direction) + val placements = mutableMapOf() + + for ((offset, requirement) in requirements) { + val absolute = Vec3i(origin.x, origin.y, origin.z) + offset + val (x, y, z) = absolute + + val existingBlock = origin.world.getBlockAt(x, y, z) + + val event = BlockPlaceEvent( + existingBlock, + existingBlock.state, + existingBlock, + player.activeItem, + player, + true, + EquipmentSlot.HAND + ).callEvent() + + if (!event) return player.userError("You can't build here!") + + placements[existingBlock] = requirement.example + } + + for ((block, placement) in placements) { + block.blockData = placement + val soundGroup = placement.soundGroup + origin.world.playSound(block.location, soundGroup.placeSound, soundGroup.volume, soundGroup.pitch) + } + + // Add sign + val signPosition = origin.getRelative(direction.oppositeFace, 1) + val signData = Material.OAK_WALL_SIGN.createBlockData { signData -> + signData as Directional + signData.facing = direction.oppositeFace + } + + signPosition.blockData = signData + val sign = signPosition.state as Sign + + // Set the detection name just in case the setup fails + sign.getSide(Side.FRONT).line(0, text("[${data.multiblock.name}]")) + sign.update() + + data.multiblock.setupSign(player, sign) + } + + data class PackagedMultiblockData( + val multiblock: Multiblock + ) + + fun getPackagedData(itemStack: ItemStack): PackagedMultiblockData? { + val data = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER) ?: return null + //TODO rework for player packaged items + val storageName = data.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING)!! + val multiblock = Multiblocks.getMultiblockByName(storageName) + + return PackagedMultiblockData(multiblock) + } + + fun packageData(data: PackagedMultiblockData, destination: PersistentDataContainer) { + val pdc = destination.adapterContext.newPersistentDataContainer() + pdc.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, data.multiblock.javaClass.simpleName) + + destination.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index d12263b6c4..c0ccb27a0d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -317,7 +317,7 @@ class MultiblockShape { edit = edit ) - fun filteredTypes(alias: String, filter: (Material) -> Boolean) = anyType(alias, MATERIALS.filter(filter)) + fun filteredTypes(alias: String, edit: BlockRequirement.() -> Unit = {}, filter: (Material) -> Boolean) = anyType(alias, MATERIALS.filter(filter), edit = edit) fun carbyne() = anyType("any concrete", CONCRETE_TYPES) { setExample(Material.GRAY_CONCRETE.createBlockData()) } @@ -338,13 +338,13 @@ class MultiblockShape { fun stainedGlassPane() = filteredTypes("any stained glass pane") { it.isStainedGlassPane } fun anyGlassPane() = filteredTypes("any stained glass") { it.isGlassPane } - fun anyStairs() = filteredTypes("any stair block") { it.isStairs } + fun anyStairs() = filteredTypes("any stair block", edit = { setExample(Material.STONE_BRICK_STAIRS.createBlockData()) }) { it.isStairs } - fun anyWall() = filteredTypes("any wall block") { it.isWall } + fun anyWall() = filteredTypes("any wall block", edit = { setExample(Material.STONE_BRICK_WALL.createBlockData()) }) { it.isWall } fun anyWool() = filteredTypes("any wool block") { it.isWool } - fun anySlab() = filteredTypes("any slab block") { it.isSlab } + fun anySlab() = filteredTypes("any slab block", edit = { setExample(Material.STONE_BRICK_SLAB.createBlockData()) }) { it.isSlab } fun anyDoubleSlab() = complete( BlockRequirement( alias = "any double slab block", @@ -368,7 +368,7 @@ class MultiblockShape { fun terracottaOrDoubleslab() { BlockRequirement( alias = "any double slab or terracotta block", - example = Material.TERRACOTTA.createBlockData(), + example = Material.CYAN_TERRACOTTA.createBlockData(), syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) val blockType = if (loadChunks) block.type else block.getTypeSafe() @@ -438,10 +438,10 @@ class MultiblockShape { fun hopper() = type(Material.HOPPER) - fun anyDoor() = filteredTypes("any door") { it.isDoor } + fun anyDoor() = filteredTypes("any door", edit = { setExample(Material.OAK_DOOR.createBlockData()) }) { it.isDoor } fun anyButton() = filteredTypes("any button") { it.isButton } - fun anyPipedInventory() = filteredTypes("any container block") { Pipes.isPipedInventory(it) } + fun anyPipedInventory() = filteredTypes("any container block", edit = { setExample(Material.CHEST.createBlockData()) }) { Pipes.isPipedInventory(it) } fun pistonBase() = type(Material.PISTON) fun pistonHead() = type(Material.PISTON_HEAD) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index f6a01d4d2f..1ce3505cab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -103,6 +103,8 @@ object NamespacedKeys { val NODES = key("chunk_nodes") + + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs From 03cfd649a495d7b34fd51e7eaf2e789e53e5ac10 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 27 Aug 2024 14:21:21 -0500 Subject: [PATCH 103/500] World multiblock manager --- .../multiblock/entity/MultiblockEntity.kt | 21 +++++++------ .../entity/MultiblockEntityInitializer.kt | 2 +- .../entity/type/ProcessingMultiblockEntity.kt | 20 ++++++------ .../multiblock/newer/MultiblockEntities.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 16 +++++----- .../powerbank/new/NewPowerBankMultiblock.kt | 20 ++++++------ .../new/NewPowerBankMultiblockTier1.kt | 16 +++++----- .../new/NewPowerBankMultiblockTier2.kt | 16 +++++----- .../new/NewPowerBankMultiblockTier3.kt | 16 +++++----- .../type/starshipweapon/EntityMultiblock.kt | 16 +++++----- .../{ => world}/ChunkMultiblockManager.kt | 4 ++- .../world/WorldMultiblockManager.kt | 31 +++++++++++++++++++ .../ion/server/features/world/IonWorld.kt | 3 ++ .../server/features/world/chunk/IonChunk.kt | 2 +- 14 files changed, 112 insertions(+), 73 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{ => world}/ChunkMultiblockManager.kt (97%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 23411f8daf..43a67c6cc8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.entity -import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -27,14 +27,14 @@ import org.bukkit.block.Sign * @param facing The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( - val manager: ChunkMultiblockManager, - val multiblock: Multiblock, - - var x: Int, - var y: Int, - var z: Int, - var world: World, - var facing: BlockFace + val manager: ChunkMultiblockManager, + val multiblock: Multiblock, + + var x: Int, + var y: Int, + var z: Int, + var world: World, + var facing: BlockFace ): PDCSerializable { /** Mark this entity as having been removed */ var removed: Boolean = false @@ -62,6 +62,9 @@ abstract class MultiblockEntity( manager.removeMultiblockEntity(x, y, z) } + /** Logic to be run upon the unloading of the chunk holding this entity */ + open fun handleUnload() {} + /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt index 93b7fcbaa3..7acb4aa660 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.entity -import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.data.DataFixer import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt index 8c961d69bd..2372c4be5f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.entity.type -import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.World import org.bukkit.block.BlockFace @@ -16,15 +16,15 @@ import org.bukkit.persistence.PersistentDataType * @param currentProgress The current progress of the process **/ abstract class ProcessingMultiblockEntity( - manager: ChunkMultiblockManager, - type: Multiblock, - x: Int, - y: Int, - z: Int, - world: World, - signOffset: BlockFace, - val requiredProgress: Int, - var currentProgress: Int = 0 + manager: ChunkMultiblockManager, + type: Multiblock, + x: Int, + y: Int, + z: Int, + world: World, + signOffset: BlockFace, + val requiredProgress: Int, + var currentProgress: Int = 0 ) : MultiblockEntity(manager, type, x, y, z, world, signOffset), SyncTickingMultiblockEntity { //TODO // -recipe system diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt index 713dcb014b..291ae93b7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.newer -import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index f20f803e52..284a929985 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -4,7 +4,6 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED -import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -12,6 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMul import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -54,13 +54,13 @@ object TestMultiblock : Multiblock(), EntityMultiblock { * Create the multiblock entity using the stored data **/ fun createEntity( - manager: ChunkMultiblockManager, - data: PersistentMultiblockData, - world: World, - x: Int, - y: Int, - z: Int, - signOffset: BlockFace + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + signOffset: BlockFace ): T fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): T? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt index 027afdbf53..e434d5f045 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt @@ -1,6 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock +package net.horizonsend.ion.server.features.multiblock.world import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt new file mode 100644 index 0000000000..1647760344 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt @@ -0,0 +1,31 @@ +package net.horizonsend.ion.server.features.multiblock.world + +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.world.IonWorld +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.LinkedBlockingQueue +import kotlin.reflect.KClass + +/** Contains multiblocks that need to be stored at a world level, such as base shields, mob defenders, etc. */ +class WorldMultiblockManager(val world: IonWorld) { + private val worldMultiblocks: ConcurrentHashMap, LinkedBlockingQueue> = ConcurrentHashMap() + + fun register(multiblockEntity: MultiblockEntity): Boolean { + val kClass = multiblockEntity::class + return worldMultiblocks.getOrPut(kClass) { LinkedBlockingQueue() }.add(multiblockEntity) + } + + fun deregister(multiblockEntity: MultiblockEntity): Boolean { + val kClass = multiblockEntity::class + val success = worldMultiblocks.getOrPut(kClass) { LinkedBlockingQueue() }.remove(multiblockEntity) + + if (!success) IonServer.slF4JLogger.warn("Tried to deregister multiblock entity that was not registered!") + return success + } + + operator fun get(type: KClass): Collection { + @Suppress("UNCHECKED_CAST") + return worldMultiblocks[type] as Collection + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 0380990111..dfb9462d9a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.common.utils.configuration.Configuration import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.machine.AreaShields +import net.horizonsend.ion.server.features.multiblock.world.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk @@ -41,6 +42,8 @@ class IonWorld private constructor( val regionPositions: ConcurrentHashMap = ConcurrentHashMap() val chunkRegions: MutableSet = ObjectOpenHashSet() + val multiblockManager = WorldMultiblockManager(this) + /** * Gets the IonChunk at the specified coordinates if it is loaded **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 8ca6600605..63236422ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.world.chunk import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.data.ChunkDataFixer From 37e7035d5aea588fb124a5d083d2b2829846bbdf Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 13:47:23 -0500 Subject: [PATCH 104/500] World multiblock manager, data upgraders, mob defender upgraded --- .../multiblock/MultiblockNameUpgrader.kt | 33 -------- .../multiblock/MultiblockStructureFixer.kt | 51 ------------- .../server/features/multiblock/Multiblocks.kt | 2 - .../multiblock/entity/MultiblockEntity.kt | 2 +- .../entity/MultiblockEntityFixer.kt | 34 --------- .../entity/MultiblockEntityInitializer.kt | 30 -------- .../multiblock/newer/MultiblockAccess.kt | 26 +++++-- .../newer/MultiblockRegistration.kt | 2 + .../multiblock/type/misc/MobDefender.kt | 76 +++++-------------- .../ion/server/features/world/IonWorld.kt | 13 +++- .../server/features/world/chunk/IonChunk.kt | 19 ++++- .../features/world/data/ChunkDataFixer.kt | 12 +-- .../server/features/world/data/DataFixer.kt | 6 +- .../server/features/world/data/DataFixers.kt | 73 ++++++++++++++++++ .../world/data/MultiblockEntityDataFixer.kt | 10 +++ .../world/data/MultiblockSignDataFixer.kt | 10 +++ .../features/world/data/SignFixerEntrance.kt | 20 +++++ .../features/world/data/WorldDataFixer.kt | 7 ++ .../multiblock/MultiblockEntityInitializer.kt | 52 +++++++++++++ .../ion/server/listener/misc/BlockListener.kt | 9 --- .../miscellaneous/registrations/Components.kt | 2 + 21 files changed, 253 insertions(+), 236 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockEntityDataFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/WorldDataFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt deleted file mode 100644 index 09d7a9172c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockNameUpgrader.kt +++ /dev/null @@ -1,33 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock - -import net.horizonsend.ion.server.features.world.data.DataFixer -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import org.bukkit.block.Sign -import org.bukkit.persistence.PersistentDataType - -object MultiblockNameUpgrader : DataFixer { - private val upgraders: MutableMap = mutableMapOf() - - override fun registerFixers() { - registerUpgrader("NavigationComputerMultiblockAdvanced", "HorizontalNavigationComputerMultiblockAdvanced") - } - - private fun registerUpgrader(previous: String, new: String) { - upgraders[previous] = new - } - - fun upgrade(sign: Sign) { - var nextName: String? = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return - var newName: String? = null - - while (nextName != null) { - newName = nextName - nextName = upgraders[nextName] - } - - if (newName == null) return - sign.persistentDataContainer.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, newName) - Tasks.syncBlocking { sign.update() } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt deleted file mode 100644 index b1d671cb08..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockStructureFixer.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock - -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.world.data.DataFixer -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.block.Sign -import org.bukkit.persistence.PersistentDataType - -/** - * Upgrades a multiblock's structure to a new version, before detection - **/ -object MultiblockStructureFixer : DataFixer { - /** - * Map of multiblock identifying strings to upgraders - **/ - private val fixers = mutableMapOf() - - override fun registerFixers() { - - } - - fun upgrade(sign: Sign): Boolean { - val name = sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return false - - return upgrade(sign) - } - - private class StructureUpgrader( - override val multiblock: Multiblock, - override val dataVersion: Int, - val previousShape: MultiblockShape, - val newShape: MultiblockShape - ) : MultiblockUpgrader { - override fun apply(sign: Sign) { - //TODO - } - } - - private class SignUpgrader(override val multiblock: Multiblock, override val dataVersion: Int) : MultiblockUpgrader { - override fun apply(sign: Sign) { - //TODO - } - } - - private sealed interface MultiblockUpgrader { - val dataVersion: Int - val multiblock: Multiblock - - fun apply(sign: Sign) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 1426161149..c74941aa05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -351,7 +351,6 @@ object Multiblocks : IonServerComponent() { /** Check if a sign has been registered as a multiblock, if so, return that value */ fun getFromPDC(sign: Sign): Multiblock? { - MultiblockNameUpgrader.upgrade(sign) return getFromPDC(sign.persistentDataContainer) } @@ -418,7 +417,6 @@ object Multiblocks : IonServerComponent() { if (cached != null) return cached val sign = getBukkitBlockState(block, loadChunks) as? Sign ?: return null - MultiblockNameUpgrader.upgrade(sign) for ((name, multiblock) in multiblocks) { if (!matchesPersistentDataContainer(sign.persistentDataContainer, multiblock)) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 43a67c6cc8..b9cdc5c051 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -68,7 +68,7 @@ abstract class MultiblockEntity( /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ - abstract fun storeAdditionalData(store: PersistentMultiblockData) + protected open fun storeAdditionalData(store: PersistentMultiblockData) {} /** * Returns the serializable data for this multiblock entity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt deleted file mode 100644 index 0460608078..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityFixer.kt +++ /dev/null @@ -1,34 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity - -import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.features.world.data.DataFixer - -object MultiblockEntityFixer : DataFixer { - private val fixers: MutableList> = mutableListOf() - - private fun addDataUpgrader(name: String, dataVersion: Int, apply: T.() -> Unit) { - fixers.add(DataUpgrader(name, dataVersion, apply)) - } - - override fun registerFixers() { - // Don't need any yet - } - - private class DataUpgrader(@Suppress("unused") val name: String, val dataVersion: Int, private val applicator: T.() -> Unit) { - fun apply(multiblock: T) = applicator.invoke(multiblock) - } - - fun upgrade(chunk: IonChunk) { - chunk.multiblockManager.getAllMultiblockEntities().values.forEach { - upgrade(it, chunk.dataVersion) - } - } - - fun upgrade(multiblockEntity: T, dataVersion: Int) { - val fixersFor = fixers - .filterIsInstance>() - .filter { it.dataVersion > dataVersion } - - fixersFor.forEach { it.apply(multiblockEntity) } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt deleted file mode 100644 index 7acb4aa660..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntityInitializer.kt +++ /dev/null @@ -1,30 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity - -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.features.world.data.DataFixer -import org.bukkit.block.Sign - -/** - * Migrates multiblocks without entities to - **/ -object MultiblockEntityInitializer : DataFixer { - private val initializers: MutableMap> = mutableMapOf() - - override fun registerFixers() { - - } - - private class Initializer(@Suppress("unused") val name: String, private val applicator: Sign.() -> T) { - fun apply(multiblock: Sign): T = applicator.invoke(multiblock) - } - - fun upgrade(sign: Sign, entityManager: ChunkMultiblockManager) { - val multiblock = Multiblocks.getFromPDC(sign) ?: return - val initializer = initializers[multiblock] ?: return - - val multiblockEntity = initializer.apply(sign) - entityManager.addMultiblockEntity(multiblockEntity) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 85aaf861d3..6afa6a52df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -16,7 +16,7 @@ import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.r import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -37,7 +37,7 @@ import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.inventory.EquipmentSlot -import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataType.STRING import java.util.Optional import java.util.concurrent.TimeUnit import kotlin.jvm.optionals.getOrNull @@ -45,6 +45,20 @@ import kotlin.jvm.optionals.getOrNull object MultiblockAccess : IonServerComponent() { private val multiblockCache: MutableMap, Optional>> = mutableMapOf() + /** + * Quickly gets the multiblock type stored in the sign. Does not check for structure + **/ + fun getFast(sign: Sign): Multiblock? { + val (x, y, z) = Vec3i(sign.x, sign.y, sign.z).getRelative(sign.getFacing().oppositeFace) + + val cached = getCachedMultiblock(sign.world, x, y, z, sign.getFacing().oppositeFace) + if (cached != null) return cached + + val value = sign.persistentDataContainer.get(MULTIBLOCK, STRING) ?: return null + + return MultiblockRegistration.getByStorageName(value) + } + /** * Access or compute the multiblock at a world position * @@ -124,7 +138,7 @@ object MultiblockAccess : IonServerComponent() { fun getMultiblock(sign: Sign, checkStructure: Boolean, loadChunks: Boolean): Multiblock? { if (!checkStructure) { - return sign.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING)?.let { + return sign.persistentDataContainer.get(MULTIBLOCK, STRING)?.let { MultiblockRegistration.getByStorageName(it) } } @@ -146,8 +160,8 @@ object MultiblockAccess : IonServerComponent() { Tasks.sync { sign.persistentDataContainer.set( - NamespacedKeys.MULTIBLOCK, - PersistentDataType.STRING, + MULTIBLOCK, + STRING, multiblock.javaClass.simpleName ) @@ -245,7 +259,7 @@ object MultiblockAccess : IonServerComponent() { val clickedBlock = event.clickedBlock ?: return val sign = clickedBlock.state as? Sign ?: return - if (sign.persistentDataContainer.has(NamespacedKeys.MULTIBLOCK)) return + if (sign.persistentDataContainer.has(MULTIBLOCK)) return val result = tryDetectMultiblock(event.player, sign, false) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index b73b9b1f3d..73d36cb68e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier2 @@ -35,6 +36,7 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(NewPowerBankMultiblockTier1) registerMultiblock(NewPowerBankMultiblockTier2) registerMultiblock(NewPowerBankMultiblockTier3) + registerMultiblock(MobDefender) } private fun sortMultiblocks() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 638c6040f2..992a19214b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -1,21 +1,22 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import org.bukkit.Bukkit import org.bukkit.Location +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.entity.Player -import java.io.File -import java.io.IOException import kotlin.math.abs -object MobDefender : Multiblock() { +object MobDefender : Multiblock(), EntityMultiblock { override val name = "mobdefender" override val signText = createSignText( @@ -68,68 +69,33 @@ object MobDefender : Multiblock() { } override fun onTransformSign(player: Player, sign: Sign) { - mobDefenders.add(sign.location) player.information("Created mob defender.") - save() // TODO: don't do this on the main thread >_> - } - - // TODO: come up with something less stupid for this - private val mobDefenders = ArrayList() - private var config = YamlConfiguration() - private val file = File(IonServer.dataFolder, "mobdefenders.yml") - - init { - Tasks.sync { - file.createNewFile() - config = YamlConfiguration.loadConfiguration(file) - for (worldName in config.getKeys(false)) { - val world = Bukkit.getWorld(worldName) ?: continue - val keys = config.getConfigurationSection(worldName)?.getKeys(false) ?: continue - for (key in keys) { - val coords = key.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - val x = coords[0].toDoubleOrNull()?.toInt() ?: continue - val y = coords[1].toDoubleOrNull()?.toInt() ?: continue - val z = coords[2].toDoubleOrNull()?.toInt() ?: continue - mobDefenders.add(Location(world, x.toDouble(), y.toDouble(), z.toDouble())) - } - } - } - } - - private fun save() { - config = YamlConfiguration() - for (location in mobDefenders) - config.set( - String.format( - "%s.%d-%d-%d", - location.world.name, location.blockX, location.blockY, - location.blockZ - ), - location.hashCode() - ) - try { - config.save(file) - } catch (e: IOException) { - e.printStackTrace() - } } fun cancelSpawn(location: Location): Boolean { if (location.world.name.lowercase().contains("eden")) return false + val mobDefenders = location.world.ion.multiblockManager[MobDefenderEntity::class] return mobDefenders.asSequence() .filter { it.world == location.world } .filter { abs(location.x - it.x) < 50 } .filter { abs(location.y - it.y) < 50 } .filter { abs(location.z - it.z) < 50 } - .mapNotNull { getBlockIfLoaded(it.world, it.blockX, it.blockY, it.blockZ) } + .mapNotNull { getBlockIfLoaded(it.world, it.x, it.y, it.z) } .mapNotNull { it.getState(false) as? Sign } .any { signMatchesStructure(it, loadChunks = false) } } - fun removeDefender(location: Location) { - if (!mobDefenders.contains(location)) return - mobDefenders.remove(location) - save() + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): MobDefenderEntity { + return MobDefenderEntity(manager, x, y, z, world, signOffset) } + + class MobDefenderEntity( + manager: ChunkMultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace + ) : MultiblockEntity(manager, MobDefender, x, y, z, world, signDirection) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index dfb9462d9a..ba029626e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -12,10 +12,12 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.configuration.DefaultWorldConfiguration +import net.horizonsend.ion.server.features.world.data.DataFixers import net.horizonsend.ion.server.features.world.environment.Environment import net.horizonsend.ion.server.features.world.environment.mobs.CustomMobSpawner import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.FORBIDDEN_BLOCKS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FORBIDDEN_BLOCKS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.mainThreadCheck import org.bukkit.Chunk @@ -25,6 +27,7 @@ import org.bukkit.event.EventHandler import org.bukkit.event.world.WorldInitEvent import org.bukkit.event.world.WorldSaveEvent import org.bukkit.event.world.WorldUnloadEvent +import org.bukkit.persistence.PersistentDataType.INTEGER import java.util.concurrent.ConcurrentHashMap import org.bukkit.persistence.PersistentDataType.LONG_ARRAY import kotlin.DeprecationLevel.ERROR @@ -33,6 +36,12 @@ class IonWorld private constructor( val world: World, val starships: MutableList = mutableListOf() ) { + var dataVersion = world.persistentDataContainer.getOrDefault(DATA_VERSION, INTEGER, 0) + set (value) { + world.persistentDataContainer.set(DATA_VERSION, INTEGER, value) + field = value + } + /** * Key: The location of the chunk packed into a long * @@ -141,6 +150,8 @@ class IonWorld private constructor( val ionWorld = IonWorld(world) ionWorlds[world] = ionWorld + DataFixers.handleWorldInit(ionWorld) + AreaShields.loadData(world) ionWorld.configuration.environments.forEach { it.setup() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 63236422ad..1f2a88c214 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.features.world.data.ChunkDataFixer +import net.horizonsend.ion.server.features.world.data.DataFixers import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES @@ -12,18 +12,25 @@ import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.world.level.chunk.LevelChunkSection import org.bukkit.Chunk import org.bukkit.World +import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.event.EventHandler import org.bukkit.event.world.ChunkLoadEvent import org.bukkit.event.world.ChunkUnloadEvent import org.bukkit.persistence.PersistentDataType.INTEGER import java.util.concurrent.ConcurrentHashMap +import java.util.function.Consumer class IonChunk( val inner: Chunk, val region: ChunkRegion, ) { - val dataVersion = inner.persistentDataContainer.getOrDefault(NamespacedKeys.DATA_VERSION, INTEGER, 0) + var dataVersion = inner.persistentDataContainer.getOrDefault(NamespacedKeys.DATA_VERSION, INTEGER, 0) + set (value) { + world.persistentDataContainer.set(NamespacedKeys.DATA_VERSION, INTEGER, value) + field = value + } + val locationKey = inner.chunkKey /** The origin X coordinate of this chunk (in real coordinates) **/ @@ -126,7 +133,7 @@ class IonChunk( ionChunk.onLoad() // Upgrade data after it has been loaded - ChunkDataFixer.upgrade(ionChunk) + DataFixers.handleChunkLoad(ionChunk) return ionChunk } @@ -156,6 +163,12 @@ class IonChunk( fun getZFromKey(key: Long): Int = (key shr 32).toInt() } + fun iterateBlocks(consumer: Consumer) { + for (x in 0..15) for (y in inner.world.minHeight until inner.world.maxHeight) for (z in 0..15) { + consumer.accept(inner.getBlock(x, y ,z)) + } + } + /** Mark this chunk as needing to be saved */ fun markUnsaved() { inner.minecraft.isUnsaved = true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt index e89ba8f52d..024917a01a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/ChunkDataFixer.kt @@ -1,15 +1,7 @@ package net.horizonsend.ion.server.features.world.data -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntityFixer import net.horizonsend.ion.server.features.world.chunk.IonChunk -object ChunkDataFixer { - const val DATA_VERSION = 1 - - fun upgrade(chunk: IonChunk) { - if (chunk.dataVersion == DATA_VERSION) return - if (chunk.dataVersion > DATA_VERSION) throw IllegalStateException("Invalid chunk data version!") - - MultiblockEntityFixer.upgrade(chunk) - } +interface ChunkDataFixer : DataFixer { + fun fix(chunk: IonChunk) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt index fc13289c14..568df607ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixer.kt @@ -1,5 +1,9 @@ package net.horizonsend.ion.server.features.world.data interface DataFixer { - fun registerFixers() + /** + * The data version this will apply to. + * If the target data's version is lower than this value, this will be triggered + **/ + val dataVersion: Int } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt new file mode 100644 index 0000000000..570cccf101 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt @@ -0,0 +1,73 @@ +package net.horizonsend.ion.server.features.world.data + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.features.world.data.fixers.multiblock.MultiblockEntityInitializer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION +import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataType.INTEGER + +object DataFixers: IonServerComponent() { + private val dataFixers = mutableListOf() + + private val worldDataFixers = mutableListOf() + private val chunkDataFixers = mutableListOf() + + private val multiblockEntityDataFixers = mutableListOf>() + private val multiblockSignDataFixers = mutableListOf() + + private fun registerFixer(fixer: DataFixer) { + dataFixers.add(fixer) + } + + private fun registerFixers() { + registerFixer(MultiblockEntityInitializer) + } + + override fun onEnable() { + registerFixers() + + // Sort by data version, ascending + // Oldest will be applied first until data is up to date + dataFixers.sortBy { it.dataVersion } + + dataFixers.filterIsInstanceTo(worldDataFixers) + dataFixers.filterIsInstanceTo(chunkDataFixers) + dataFixers.filterIsInstanceTo(multiblockEntityDataFixers) + dataFixers.filterIsInstanceTo(multiblockSignDataFixers) + } + + fun handleWorldInit(world: IonWorld) { + for (worldFixer in worldDataFixers.filter { it.dataVersion > world.dataVersion }) { + worldFixer.fix(world) + + world.dataVersion = worldFixer.dataVersion + } + } + + fun handleChunkLoad(chunk: IonChunk) { + for (chunkDataFixer in chunkDataFixers.filter { it.dataVersion > chunk.dataVersion }) { + chunkDataFixer.fix(chunk) + + chunk.dataVersion = chunkDataFixer.dataVersion + } + + SignFixerEntrance.iterateChunk(chunk) + } + + fun handleMultiblockEntityLoad() { + //TODO + } + + fun handleMultiblockSignLoad(sign: Sign) { + val dataVersion = sign.persistentDataContainer.getOrDefault(DATA_VERSION, INTEGER, 0) + + for (signFixer in multiblockSignDataFixers.filter { it.dataVersion > dataVersion }) { + signFixer.fixSign(sign) + + sign.persistentDataContainer.set(DATA_VERSION, INTEGER, signFixer.dataVersion) + sign.update() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockEntityDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockEntityDataFixer.kt new file mode 100644 index 0000000000..dd4ed573c7 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockEntityDataFixer.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.world.data + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import kotlin.reflect.KClass + +interface MultiblockEntityDataFixer : DataFixer { + val clazz: KClass + + fun fixEntity(entity: T) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt new file mode 100644 index 0000000000..1b2120ebdb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.world.data + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import org.bukkit.block.Sign + +interface MultiblockSignDataFixer : DataFixer { + val multiblock: Multiblock + + fun fixSign(sign: Sign) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt new file mode 100644 index 0000000000..5c71023632 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.world.data + +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import org.bukkit.block.Sign +import org.bukkit.block.data.type.WallSign + +object SignFixerEntrance { + fun iterateChunk(chunk: IonChunk) = Tasks.async { + chunk.iterateBlocks { + val data = it.blockData + if (data !is WallSign) return@iterateBlocks + + Tasks.sync { + val state = it.state as Sign + DataFixers.handleMultiblockSignLoad(state) + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/WorldDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/WorldDataFixer.kt new file mode 100644 index 0000000000..ee99c59680 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/WorldDataFixer.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.world.data + +import net.horizonsend.ion.server.features.world.IonWorld + +interface WorldDataFixer : DataFixer { + fun fix(world: IonWorld) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt new file mode 100644 index 0000000000..09dabdf127 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt @@ -0,0 +1,52 @@ +package net.horizonsend.ion.server.features.world.data.fixers.multiblock + +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.features.world.data.ChunkDataFixer +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import org.bukkit.block.Sign +import org.bukkit.block.data.type.WallSign + +object MultiblockEntityInitializer : ChunkDataFixer { + override fun fix(chunk: IonChunk) = Tasks.async { + chunk.iterateBlocks { + val data = it.blockData + if (data !is WallSign) return@iterateBlocks + + Tasks.sync { + val state = it.state + if (state !is Sign) return@sync + + val multiblock = MultiblockAccess.getFast(state) + if (multiblock !is EntityMultiblock<*>) return@sync + + val multiblockDirection = state.getFacing().oppositeFace + + val (x, y, z) = Vec3i(state.x, state.y, state.z).getRelative(multiblockDirection) + + val entityPresent = MultiblockEntities.getMultiblockEntity(chunk.world, x, y, z) != null + if (entityPresent) return@sync + + MultiblockEntities.setMultiblockEntity(state.world, x, y, z) { manager -> + multiblock.createEntity( + manager, + PersistentMultiblockData(x, y, z, multiblock, multiblockDirection), + state.world, + x, + y, + z, + multiblockDirection + ) + } + } + } + } + + override val dataVersion: Int = 1 +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BlockListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BlockListener.kt index 130fcd854b..f72a99af3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BlockListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BlockListener.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.listener.misc -import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded @@ -10,7 +9,6 @@ import org.bukkit.Material import org.bukkit.block.data.MultipleFacing import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority -import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPhysicsEvent import org.bukkit.event.block.SignChangeEvent import org.bukkit.event.world.StructureGrowEvent @@ -43,13 +41,6 @@ object BlockListener : SLEventListener() { event.isCancelled = true } - // Attempt to remove mob defenders at the location of blocks broken - @EventHandler(priority = EventPriority.MONITOR) - fun onBlockBreakEvent(event: BlockBreakEvent) { - if (event.isCancelled) return - MobDefender.removeDefender(event.block.location) - } - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) fun onSignChange(event: SignChangeEvent) { for (i in 0 until 4) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index ecbac9310e..7e4876dec4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -96,6 +96,7 @@ import net.horizonsend.ion.server.features.transport.pipe.filter.Filters import net.horizonsend.ion.server.features.tutorial.Tutorials import net.horizonsend.ion.server.features.waypoint.WaypointManager import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.features.world.data.DataFixers import net.horizonsend.ion.server.features.world.environment.mobs.CustomMobSpawning import net.horizonsend.ion.server.listener.misc.WorldEditListener import net.horizonsend.ion.server.miscellaneous.registrations.legacy.CustomRecipes @@ -109,6 +110,7 @@ val components: List = listOf( Caches, Discord, Notify, + DataFixers, Shuttles, ProxyMessaging, IonWorld, From bc9061d3bcb373b43ea4067fd7130f0e8557aab6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 16:00:35 -0500 Subject: [PATCH 105/500] bug fixes, utility command --- .../ion/server/command/admin/WorldCommand.kt | 32 ++++ .../server/features/machine/AreaShields.kt | 138 +++--------------- .../multiblock/entity/MultiblockEntity.kt | 7 +- .../newer/MultiblockRegistration.kt | 10 ++ .../multiblock/type/areashield/AreaShield.kt | 70 ++++++++- .../multiblock/type/misc/MobDefender.kt | 19 ++- .../world/ChunkMultiblockManager.kt | 8 + .../world/WorldMultiblockManager.kt | 14 +- .../network/holders/ChunkNetworkHolder.kt | 2 +- .../ion/server/features/world/IonWorld.kt | 3 - .../server/features/world/chunk/IonChunk.kt | 1 + .../server/features/world/data/DataFixers.kt | 6 +- .../world/data/MultiblockSignDataFixer.kt | 10 -- .../features/world/data/SignDataFixer.kt | 7 + .../features/world/data/SignFixerEntrance.kt | 27 +++- .../multiblock/MultiblockEntityInitializer.kt | 51 +++---- 16 files changed, 219 insertions(+), 186 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignDataFixer.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt index b266fd69b3..e8a4862486 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt @@ -21,12 +21,14 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.features.world.environment.Environment import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.format.TextDecoration import org.bukkit.Bukkit import org.bukkit.World import org.bukkit.command.CommandSender +import org.bukkit.entity.Player @CommandAlias("ionworld") @CommandPermission("ion.admin.world") @@ -182,4 +184,34 @@ object WorldCommand : SLCommand() { ?: "None" )) } + + @Subcommand("query entities") + fun onQueryEntities(sender: Player, type: String, @Optional page: Int?) { + val manager = sender.world.ion.multiblockManager + val keys = manager.getStoredMultiblocks() + + val clazz = keys.firstOrNull { it.simpleName == type } + + if (clazz == null) { + sender.userError("$type not found! Stored types are: ${keys.map { it.simpleName }}") + return + } + + val entities = manager[clazz].toList() + + val menu = formatPaginatedMenu( + entities.size, + "/onQueryEntities $type", + page ?: 1 + ) { + val entity = entities[it] + + ofChildren(text(entity.javaClass.simpleName), space(), bracketed(text("${entity.x} ${entity.y} ${entity.z}")),) + .clickEvent(ClickEvent.runCommand("/tp ${entity.x} ${entity.y} ${entity.z}")) + .hoverEvent(text("/tp ${entity.x} ${entity.y} ${entity.z}")) + } + + sender.information("Entities:") + sender.sendMessage(menu) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index 8fec01a170..16a5e70cc5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -1,29 +1,19 @@ package net.horizonsend.ion.server.features.machine -import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield -import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isInRange -import net.horizonsend.ion.server.miscellaneous.utils.isWallSign -import org.bukkit.Bukkit import org.bukkit.Color import org.bukkit.Location import org.bukkit.Particle -import org.bukkit.World import org.bukkit.block.Block -import org.bukkit.block.Sign -import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.event.Cancellable import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority -import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.block.BlockBurnEvent import org.bukkit.event.block.BlockExplodeEvent import org.bukkit.event.entity.EntityDamageEvent import org.bukkit.event.entity.EntityExplodeEvent -import java.io.File import java.util.concurrent.ConcurrentHashMap import kotlin.math.ceil import kotlin.math.max @@ -34,76 +24,18 @@ object AreaShields : IonServerComponent() { val bypassShieldEvents = ConcurrentHashMap.newKeySet() private var explosionPowerOverride: Double? = null - override fun onEnable() { - loadFile() - - Tasks.asyncRepeat(0L, 20L * 60L) { - saveData() - } - } - - var configuration: YamlConfiguration? = null - - //region File data - private fun loadFile() { - val areaShieldFile = File(IonServer.dataFolder, "areashields.yml") - if (!areaShieldFile.exists()) { - return - } - - configuration = YamlConfiguration.loadConfiguration(areaShieldFile) - } - - fun loadData(world: World) { - val configuration = configuration ?: return log.warn("Area Shields file not loaded.") - if (!configuration.getKeys(false).contains(world.name)) return - val worldName = world.name - - configuration.getConfigurationSection(worldName)?.getKeys(false)?.forEach { vector -> - val split = vector.split(",") - val location = Location(world, split[0].toDouble(), split[1].toDouble(), split[2].toDouble()) - val radius = configuration.getInt("$worldName.$vector") - locationRadiusMap[location] = radius - } - } - - private fun saveData() { - val file = File(IonServer.dataFolder, "areashields.yml") - - if (configuration == null) configuration = YamlConfiguration() - - for (world in Bukkit.getWorlds()) { - configuration!!.createSection(world.name) - } - - for (location in locationRadiusMap.keys) { - val worldName = location.world.name - val text = "${location.blockX},${location.blockY},${location.blockZ}" - val radius = locationRadiusMap[location] - configuration!!.getConfigurationSection(worldName)!!.set(text, radius) - } - - configuration!!.save(file) - } - //endregion - - private var locationRadiusMap = ConcurrentHashMap() - - fun register(location: Location, radius: Int) { - locationRadiusMap[location] = radius - } - - fun removeAreaShield(location: Location): Boolean { - val removed = locationRadiusMap.remove(location) - return removed != null - } - fun getNearbyAreaShields( location: Location, explosionSize: Double - ): Map = locationRadiusMap.filter { (shieldLoc: Location, shieldRadius: Int) -> - val radius = shieldRadius + explosionSize - return@filter shieldLoc.world == location.world && shieldLoc.isInRange(location, radius) + ): List { + val shields = location.world.ion.multiblockManager[AreaShield.AreaShieldEntity::class] + + return shields.filter { + val radius = it.multiblock.radius + explosionSize + val shieldLoc = it.location + + return@filter shieldLoc.world == location.world && shieldLoc.isInRange(location, radius) && !it.removed + } } fun withExplosionPowerOverride(value: Double, block: () -> Unit) { @@ -160,32 +92,25 @@ object AreaShields : IonServerComponent() { var explosionResistanceTotal = 0.0 blockList.forEach { explosionResistanceTotal += it.type.blastResistance } - for (shieldLocation in areaShields.keys) { - val block = shieldLocation.block - if (!block.type.isWallSign) { - continue - } - val sign = block.getState(false) as Sign - val multiblock = Multiblocks[sign] as? AreaShield ?: continue - - if (multiblock.radius != areaShields.get(shieldLocation)) continue - var power = PowerMachines.getPower(sign) + for (shield in areaShields) { + var power = shield.getPower() if (power <= 0) continue power -= ((blockList.size.toDouble()/explosionResistanceTotal) * 10 * (this.explosionPowerOverride ?: 1.0)).toInt() - val percent = power.toFloat() / multiblock.maxPower.toFloat() - if (usePower) PowerMachines.setPower(sign, power) + val percent = power.toFloat() / shield.maxPower.toFloat() + + if (usePower) shield.setPower(power) + val color = Color.fromRGB( min(255f, 255 - max(0f, 255 * percent)).toInt(), 0, min(255f, max(0f, 255 * percent)).toInt() ) - val center = location.toCenterLocation() - val particle = Particle.DUST val dustOptions = Particle.DustOptions(color, 100f) - center.world.spawnParticle(particle, location, 1, 0.0, 0.0, 0.0, 0.0, dustOptions, true) + location.world.spawnParticle(particle, location, 1, 0.0, 0.0, 0.0, 0.0, dustOptions, true) + shielded = true } if (shielded) blockList.clear() @@ -193,33 +118,14 @@ object AreaShields : IonServerComponent() { @EventHandler fun onEntityDamage(event: EntityDamageEvent) { - if ( - event.cause != EntityDamageEvent.DamageCause.BLOCK_EXPLOSION && + if (event.cause != EntityDamageEvent.DamageCause.BLOCK_EXPLOSION && event.cause != EntityDamageEvent.DamageCause.ENTITY_EXPLOSION - ) { - return - } + ) return val areaShields = getNearbyAreaShields(event.entity.location, 1.0) - for (shieldLocation in areaShields.keys) { - val block = shieldLocation.block - if (!block.type.isWallSign) continue - val sign = block.getState(false) as Sign - val multiblock = Multiblocks[sign] as? net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield ?: continue - if (multiblock.radius != areaShields[shieldLocation]) continue - if (PowerMachines.getPower(sign) > 0) event.isCancelled = true - } - } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - fun onBlockBreak(event: BlockBreakEvent) { - if (removeAreaShield(event.block.location)) { - event.player.sendActionBar("Removed area shield") + for (shield in areaShields) { + if (shield.getPower() > 0) event.isCancelled = true } } - - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - fun onBlockBurn(event: BlockBurnEvent) { - removeAreaShield(event.block.location) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index b9cdc5c051..a6d3dd9909 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -28,7 +28,7 @@ import org.bukkit.block.Sign **/ abstract class MultiblockEntity( val manager: ChunkMultiblockManager, - val multiblock: Multiblock, + open val multiblock: Multiblock, var x: Int, var y: Int, @@ -63,7 +63,10 @@ abstract class MultiblockEntity( } /** Logic to be run upon the unloading of the chunk holding this entity */ - open fun handleUnload() {} + open fun onUnload() {} + + /** Logic to be run upon the loading of the chunk holding this entity, or its creation */ + open fun onLoad() {} /** * Stores any additional data for this multiblock (e.g. power, owner, etc) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 73d36cb68e..2351a3e73e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -6,6 +6,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield10 +import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield20 +import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield30 +import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield5 import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 @@ -36,6 +40,12 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(NewPowerBankMultiblockTier1) registerMultiblock(NewPowerBankMultiblockTier2) registerMultiblock(NewPowerBankMultiblockTier3) + + registerMultiblock(AreaShield5) + registerMultiblock(AreaShield10) + registerMultiblock(AreaShield20) + registerMultiblock(AreaShield30) + registerMultiblock(MobDefender) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt index 24b531459f..517566f6ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt @@ -1,25 +1,36 @@ package net.horizonsend.ion.server.features.multiblock.type.areashield +import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.machine.AreaShields +import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks -import org.bukkit.ChatColor import org.bukkit.Material import org.bukkit.Particle +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataType.INTEGER import java.util.concurrent.TimeUnit -abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultiblock, InteractableMultiblock { +abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultiblock, InteractableMultiblock, EntityMultiblock { override fun onTransformSign(player: Player, sign: Sign) { - AreaShields.register(sign.location, radius) - player.sendMessage(ChatColor.GREEN.toString() + "Area Shield created.") + player.success("Area Shield created.") } override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { @@ -64,4 +75,53 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultibloc null, "&8Radius: &a$radius" ) + + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): AreaShieldEntity { + return AreaShieldEntity( + manager, + this, + x, + y, + z, + world, + signOffset, + data.getAdditionalDataOrDefault(POWER, INTEGER, 0), + maxPower + ) + } + + class AreaShieldEntity( + manager: ChunkMultiblockManager, + override val multiblock: AreaShield, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override var powerUnsafe: Int, + override val maxPower: Int + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, SimpleTextDisplayPoweredMultiblockEntity { + override val powerDisplay: TextDisplayHandler = createTextDisplayHandler(this) + + override fun onLoad() { + world.ion.multiblockManager.register(this) + } + + override fun handleRemoval() { + world.ion.multiblockManager.deregister(this) + powerDisplay.remove() + } + + override fun onUnload() { + world.ion.multiblockManager.deregister(this) + } + + override fun updatePowerVisually() { + powerDisplay.update() + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(POWER, INTEGER, getPower()) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 992a19214b..49b08498c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.Location import org.bukkit.World import org.bukkit.block.BlockFace @@ -81,9 +80,7 @@ object MobDefender : Multiblock(), EntityMultiblock() }.add(multiblockEntity) + return getCollection(kClass).add(multiblockEntity) } fun deregister(multiblockEntity: MultiblockEntity): Boolean { val kClass = multiblockEntity::class - val success = worldMultiblocks.getOrPut(kClass) { LinkedBlockingQueue() }.remove(multiblockEntity) + val success = getCollection(kClass).remove(multiblockEntity) if (!success) IonServer.slF4JLogger.warn("Tried to deregister multiblock entity that was not registered!") return success } + private fun getCollection(type: KClass): LinkedBlockingQueue { + return worldMultiblocks.getOrPut(type) { LinkedBlockingQueue() } + } + operator fun get(type: KClass): Collection { @Suppress("UNCHECKED_CAST") - return worldMultiblocks[type] as Collection + return getCollection(type) as Collection + } + + fun getStoredMultiblocks(): Set> { + return worldMultiblocks.keys } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt index c7ea86f535..7dcba33a4b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt @@ -61,7 +61,7 @@ class ChunkNetworkHolder private constructor (val manager: network.namespacedKey, PersistentDataType.TAG_CONTAINER ) ?: run { - IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") +// IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") chunkPDC.adapterContext.newPersistentDataContainer() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index ba029626e6..c47668bc3f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -6,7 +6,6 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.configuration.Configuration import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.machine.AreaShields import net.horizonsend.ion.server.features.multiblock.world.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.world.chunk.ChunkRegion @@ -152,8 +151,6 @@ class IonWorld private constructor( DataFixers.handleWorldInit(ionWorld) - AreaShields.loadData(world) - ionWorld.configuration.environments.forEach { it.setup() } Tasks.syncRepeat(10, 10, ionWorld::tickEnvironments) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 1f2a88c214..020ec35955 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -66,6 +66,7 @@ class IonChunk( **/ fun onUnload() { save() + multiblockManager.onUnload() transportNetwork.onUnload() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt index 570cccf101..72138d7677 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt @@ -15,7 +15,7 @@ object DataFixers: IonServerComponent() { private val chunkDataFixers = mutableListOf() private val multiblockEntityDataFixers = mutableListOf>() - private val multiblockSignDataFixers = mutableListOf() + private val signDataFixers = mutableListOf() private fun registerFixer(fixer: DataFixer) { dataFixers.add(fixer) @@ -35,7 +35,7 @@ object DataFixers: IonServerComponent() { dataFixers.filterIsInstanceTo(worldDataFixers) dataFixers.filterIsInstanceTo(chunkDataFixers) dataFixers.filterIsInstanceTo(multiblockEntityDataFixers) - dataFixers.filterIsInstanceTo(multiblockSignDataFixers) + dataFixers.filterIsInstanceTo(signDataFixers) } fun handleWorldInit(world: IonWorld) { @@ -63,7 +63,7 @@ object DataFixers: IonServerComponent() { fun handleMultiblockSignLoad(sign: Sign) { val dataVersion = sign.persistentDataContainer.getOrDefault(DATA_VERSION, INTEGER, 0) - for (signFixer in multiblockSignDataFixers.filter { it.dataVersion > dataVersion }) { + for (signFixer in signDataFixers.filter { it.dataVersion > dataVersion }) { signFixer.fixSign(sign) sign.persistentDataContainer.set(DATA_VERSION, INTEGER, signFixer.dataVersion) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt deleted file mode 100644 index 1b2120ebdb..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/MultiblockSignDataFixer.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.world.data - -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign - -interface MultiblockSignDataFixer : DataFixer { - val multiblock: Multiblock - - fun fixSign(sign: Sign) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignDataFixer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignDataFixer.kt new file mode 100644 index 0000000000..27000707e6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignDataFixer.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.world.data + +import org.bukkit.block.Sign + +interface SignDataFixer : DataFixer { + fun fixSign(sign: Sign) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt index 5c71023632..58e8996f59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt @@ -2,17 +2,32 @@ package net.horizonsend.ion.server.features.world.data import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.block.Sign -import org.bukkit.block.data.type.WallSign object SignFixerEntrance { fun iterateChunk(chunk: IonChunk) = Tasks.async { - chunk.iterateBlocks { - val data = it.blockData - if (data !is WallSign) return@iterateBlocks + val chunkSnapshot = chunk.inner.getChunkSnapshot(true, false, false) + val signBlocks = mutableSetOf() + + for (x in 0..15) for (z in 0..15) { + val minBlockY = chunk.world.minHeight + val maxBlockY = chunkSnapshot.getHighestBlockYAt(x, z) + + for (y in minBlockY..maxBlockY) { + val blockType = chunkSnapshot.getBlockType(x, y, z) + + if (!blockType.isWallSign) continue + signBlocks.add(Vec3i(x, y, z)) + } + } + + Tasks.sync { + for ((x, y, z) in signBlocks) { + val block = chunk.inner.getBlock(x, y, z) + val state = block.state as Sign - Tasks.sync { - val state = it.state as Sign DataFixers.handleMultiblockSignLoad(state) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt index 09dabdf127..6ad613f77a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt @@ -4,47 +4,34 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock -import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.features.world.data.ChunkDataFixer -import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.features.world.data.SignDataFixer import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.block.Sign -import org.bukkit.block.data.type.WallSign -object MultiblockEntityInitializer : ChunkDataFixer { - override fun fix(chunk: IonChunk) = Tasks.async { - chunk.iterateBlocks { - val data = it.blockData - if (data !is WallSign) return@iterateBlocks +object MultiblockEntityInitializer : SignDataFixer { + override fun fixSign(sign: Sign) { + val multiblock = MultiblockAccess.getFast(sign) + if (multiblock !is EntityMultiblock<*>) return - Tasks.sync { - val state = it.state - if (state !is Sign) return@sync + val multiblockDirection = sign.getFacing().oppositeFace - val multiblock = MultiblockAccess.getFast(state) - if (multiblock !is EntityMultiblock<*>) return@sync + val (x, y, z) = Vec3i(sign.x, sign.y, sign.z).getRelative(multiblockDirection) - val multiblockDirection = state.getFacing().oppositeFace + val entityPresent = MultiblockEntities.getMultiblockEntity(sign.world, x, y, z) != null + if (entityPresent) return - val (x, y, z) = Vec3i(state.x, state.y, state.z).getRelative(multiblockDirection) - - val entityPresent = MultiblockEntities.getMultiblockEntity(chunk.world, x, y, z) != null - if (entityPresent) return@sync - - MultiblockEntities.setMultiblockEntity(state.world, x, y, z) { manager -> - multiblock.createEntity( - manager, - PersistentMultiblockData(x, y, z, multiblock, multiblockDirection), - state.world, - x, - y, - z, - multiblockDirection - ) - } - } + MultiblockEntities.setMultiblockEntity(sign.world, x, y, z) { manager -> + multiblock.createEntity( + manager, + PersistentMultiblockData(x, y, z, multiblock, multiblockDirection), + sign.world, + x, + y, + z, + multiblockDirection + ) } } From 8c6f4f4b5e173984fdcfb0b583aa68a3b7fdf111 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 18:38:23 -0500 Subject: [PATCH 106/500] Solar panel improvements + misc bug fixes --- .../server/command/admin/IonChunkCommand.kt | 2 +- .../ion/server/command/qol/SetPowerCommand.kt | 29 +++++----- .../multiblock/type/areashield/AreaShield.kt | 12 ++--- .../powerbank/new/NewPowerBankMultiblock.kt | 4 ++ .../transport/node/gas/GasJunctionNode.kt | 8 +++ .../transport/node/gas/GasNodeFactory.kt | 5 +- .../transport/node/general/JunctionNode.kt | 10 ---- .../transport/node/power/PowerNodeFactory.kt | 10 ++-- .../transport/node/power/SolarPanelNode.kt | 53 ++++++++++++------- .../transport/node/power/SpongeNode.kt | 2 + .../features/world/chunk/ChunkRegion.kt | 4 ++ .../persistence/NamespacedKeys.kt | 1 + 12 files changed, 84 insertions(+), 56 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index ce69698c9a..419f1cc8db 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -99,7 +99,7 @@ object IonChunkCommand : SLCommand() { val ionChunk = sender.chunk.ion() sender.information("Chunk: $ionChunk") - sender.information("Region: ${ionChunk.region}") + sender.information("Region: ${ionChunk.region}, last ticked: ${ionChunk.region.lastTicked}") sender.information("World has: ${ionChunk.world.ion.regionPositions.values.distinct().size} unique regions") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt index ac0ff7d718..1eaf7867b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt @@ -4,14 +4,13 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Default -import co.aikar.commands.annotation.Optional import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.command.admin.debug -import net.horizonsend.ion.server.features.machine.PowerMachines.setPower +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities import net.horizonsend.ion.server.miscellaneous.utils.getSelection -import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.entity.Player @CommandAlias("setpower") @@ -20,31 +19,35 @@ object SetPowerCommand : SLCommand() { @Default @Suppress("unused") @CommandCompletion("0|1000|500000|2147483647 true|false") - fun onSetPower(sender: Player, amount: Int, @Optional ignoreLimit: Boolean?) { + fun onSetPower(sender: Player, amount: Int) { val maxSelectionVolume = 200000 - val selection = sender.getSelection() ?: return + val selection = runCatching { sender.getSelection() }.getOrNull() ?: fail { "You must make a selection!" } - if(selection.volume > maxSelectionVolume) { + if (selection.volume > maxSelectionVolume) { sender.userError("Selection too large! The maximum volume is $maxSelectionVolume.") return } - if(sender.world.name != selection.world?.name) return + if (sender.world.name != selection.world?.name) return + + var hits = 0 for (blockPosition in selection) { val x = blockPosition.x() val y = blockPosition.y() val z = blockPosition.z() - val block = sender.world.getBlockAt(x, y, z) sender.debug("checking block at $x $y $z") - if (!block.type.isWallSign) continue - val sign = block.state as? org.bukkit.block.Sign ?: continue - sender.debug("sign found at $x $y $z") - setPower(sign, amount, fast = ignoreLimit ?: false) + val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) + if (entity !is PoweredMultiblockEntity) continue + + entity.setPower(amount) + hits++ + sender.debug("power sent") } - sender.success("Set multiblock power to $amount.") + + sender.success("Set power to $amount in $hits multiblocks.") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt index 517566f6ac..254ada49cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.features.client.display.container.TextDisplayH import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock @@ -100,10 +99,12 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultibloc signDirection: BlockFace, override var powerUnsafe: Int, override val maxPower: Int - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, SimpleTextDisplayPoweredMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { override val powerDisplay: TextDisplayHandler = createTextDisplayHandler(this) override fun onLoad() { + powerDisplay.update() + world.ion.multiblockManager.register(this) } @@ -116,12 +117,11 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultibloc world.ion.multiblockManager.deregister(this) } - override fun updatePowerVisually() { - powerDisplay.update() - } - override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(POWER, INTEGER, getPower()) } + + override fun toString(): String = "AREA SHIELD::: POWER:: ${getPower()}" + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 60e951051d..1ec4ba85be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -109,6 +109,10 @@ abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMu ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { override val powerDisplay: TextDisplayHandler = createTextDisplayHandler(this) + override fun onLoad() { + powerDisplay.update() + } + override fun handleRemoval() { powerDisplay.remove() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt index 17456593ec..56cc30965a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt @@ -12,4 +12,12 @@ class GasJunctionNode(network: GasNetwork) : JunctionNode(network) { @@ -18,10 +17,10 @@ class GasNodeFactory(network: GasNetwork) : NodeFactory(network) { when { // Straight wires - snapshot.type == Material.END_ROD -> addLightningRod(snapshot.data as Directional, key) +// snapshot.type == Material.END_ROD -> addLightningRod(snapshot.data as Directional, key) // Omnidirectional wires - snapshot.type == Material.SPONGE -> addJunction(key) +// snapshot.type == Material.SPONGE -> addJunction(key) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 2aca88eea0..2e7eb5332c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -58,14 +58,4 @@ abstract class JunctionNode, B: Ju override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() .filterNot { head.previousNodes.contains(it.first) } .firstOrNull() - -// override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" - - override fun toString(): String { - return """ - [Gas Junction Node] - ${positions.size} positions - Relationships: ${relationships.joinToString { it.sideTwo.toString() }} - """.trimIndent() - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 6c46b5815a..d9ea787f89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN +import org.bukkit.block.BlockFace.UP import org.bukkit.block.data.Directional class PowerNodeFactory(network: PowerNetwork) : NodeFactory(network) { @@ -143,7 +144,8 @@ class PowerNodeFactory(network: PowerNetwork) : NodeFactory(networ **/ suspend fun addSolarPanel(position: BlockKey, handleRelationships: Boolean = true) { // The diamond and daylight detector - val panelPositions = (1..2).map { getRelative(position, BlockFace.UP, it) } + val diamondPosition = getRelative(position, UP, 1) + val detectorPosition = getRelative(position, UP, 2) // Get the nodes that might be touching the solar panel // @@ -171,11 +173,11 @@ class PowerNodeFactory(network: PowerNetwork) : NodeFactory(networ val node = when (neighboringNodes.size) { 0 -> SolarPanelNode(network).apply { network.solarPanels += this - }.addPosition(position, panelPositions) + }.addPosition(position, diamondPosition, detectorPosition) - 1 -> neighboringNodes.firstOrNull()?.addPosition(position, panelPositions) ?: throw ConcurrentModificationException("Node removed during processing") + 1 -> neighboringNodes.firstOrNull()?.addPosition(position, diamondPosition, detectorPosition) ?: throw ConcurrentModificationException("Node removed during processing") - in 2..4 -> handleMerges(neighboringNodes).addPosition(position, panelPositions) + in 2..4 -> handleMerges(neighboringNodes).addPosition(position, diamondPosition, detectorPosition) else -> throw IllegalArgumentException() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 293957d616..c96c45bfa0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.features.transport.step.origin.power.SolarPowe import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -21,9 +22,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.firsts -import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.minecraft.core.BlockPos -import net.minecraft.world.level.LightLayer +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.GameRule import org.bukkit.Material import org.bukkit.World @@ -31,13 +30,11 @@ import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.BlockFace.SELF import org.bukkit.block.BlockFace.UP +import org.bukkit.block.data.AnaloguePowerable import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.LONG_ARRAY import java.util.concurrent.ConcurrentHashMap import java.util.function.Consumer -import kotlin.math.PI -import kotlin.math.max -import kotlin.math.sin /** * Represents a solar panel, or multiple @@ -54,6 +51,9 @@ class SolarPanelNode( /** The positions of extractors in this solar panel */ private val extractorPositions = ConcurrentHashMap.newKeySet() + /** The positions of daylight detectors in this solar panel */ + private val detectorPositions = ConcurrentHashMap.newKeySet() + /** The number of solar cells contained in this node */ private val cellNumber: Int get() = extractorPositions.size @@ -152,16 +152,7 @@ class SolarPanelNode( network.world.environment == World.Environment.NORMAL && network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true ) { - // Sample position - val sample = positions.first() - val pos = BlockPos(getX(sample), getY(sample), getZ(sample)) - val lightLevel = network.world.minecraft.getBrightness(LightLayer.SKY, pos) - - if (lightLevel == 0) return 0 - - // Calculate via sine curve otherwise - val daylight = sin((network.world.time / (12000.0 / PI)) - (PI / 2)) - max(0.0, daylight) * 1.5 // 1.5 to bring area under curve to around equal with night + getPowerRatio() } else 0.5 val time = System.currentTimeMillis() @@ -170,6 +161,21 @@ class SolarPanelNode( return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() } + /** + * Calculates the light level at the detectors + **/ + private fun getPowerRatio(): Double { + val total = detectorPositions.size * 15 + val sum = detectorPositions.sumOf { + val data = getBlockDataSafe(network.world, getX(it), getY(it), getZ(it)) ?: return@sumOf 0 + if (data !is AnaloguePowerable) return@sumOf 0 + + data.power + } + + return sum.toDouble() / total.toDouble() + } + /** * Execute the provided consumer across every interconnected solar node * @@ -224,7 +230,7 @@ class SolarPanelNode( rebuildNode(position) } - suspend fun addPosition(extractorKey: BlockKey, others: Iterable): SolarPanelNode { + suspend fun addPosition(extractorKey: BlockKey, diamondKey: BlockKey, detectorKey: BlockKey): SolarPanelNode { extractorPositions += extractorKey // Make sure there isn't still an extractor @@ -232,7 +238,10 @@ class SolarPanelNode( addPosition(extractorKey) buildRelations(extractorKey) - positions += others + positions += diamondKey + positions += detectorKey + + detectorPositions += detectorKey for (position: BlockKey in positions) { network.nodes[position] = this @@ -261,6 +270,7 @@ class SolarPanelNode( override suspend fun rebuildNode(position: BlockKey) { network.solarPanels.remove(this) + detectorPositions.clear() // Create new nodes, automatically merging together extractorPositions.forEach { @@ -277,6 +287,7 @@ class SolarPanelNode( super.drainTo(new) new.extractorPositions.addAll(extractorPositions) + new.detectorPositions.addAll(detectorPositions) } override fun loadIntoNetwork() { @@ -287,6 +298,7 @@ class SolarPanelNode( override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) persistentDataContainer.set(SOLAR_CELL_EXTRACTORS, LONG_ARRAY, extractorPositions.toLongArray()) + persistentDataContainer.set(SOLAR_CELL_DETECTORS, LONG_ARRAY, detectorPositions.toLongArray()) } override fun loadData(persistentDataContainer: PersistentDataContainer) { @@ -295,6 +307,9 @@ class SolarPanelNode( val extractors = persistentDataContainer.get(SOLAR_CELL_EXTRACTORS, LONG_ARRAY) extractors?.let { extractorPositions.addAll(it.asIterable()) } + + val detectors = persistentDataContainer.get(SOLAR_CELL_DETECTORS, LONG_ARRAY) + detectors?.let { detectorPositions.addAll(it.asIterable()) } } companion object { @@ -311,5 +326,5 @@ class SolarPanelNode( } } - override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().firsts().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance" + override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().firsts().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance, powerRatio = ${getPowerRatio()}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 76778b8bbf..a275108859 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -17,4 +17,6 @@ class SpongeNode(network: PowerNetwork) : JunctionNode Date: Wed, 28 Aug 2024 20:00:56 -0500 Subject: [PATCH 107/500] power display improvements --- .../display/container/DisplayHandlerHolder.kt | 21 +++++++++++++++ .../display/container/DisplayHandlers.kt | 27 +++++++++++++++++++ .../display/container/TextDisplayHandler.kt | 1 + ...impleTextDisplayPoweredMultiblockEntity.kt | 12 ++++++--- .../multiblock/type/areashield/AreaShield.kt | 18 ++++++++++--- .../powerbank/new/NewPowerBankMultiblock.kt | 17 +++++++++--- .../features/transport/TransportManager.kt | 4 +-- .../transport/node/power/PowerFlowMeter.kt | 25 ++++++++++++++--- .../miscellaneous/registrations/Components.kt | 5 ++-- .../miscellaneous/registrations/Listeners.kt | 2 ++ 10 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt new file mode 100644 index 0000000000..83dee127a0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt @@ -0,0 +1,21 @@ +package net.horizonsend.ion.server.features.client.display.container + +interface DisplayHandlerHolder { + val displayHandler: TextDisplayHandler + + fun refresh() + + fun isValid(): Boolean + + fun removeDisplay() { + displayHandler.remove() + } + + fun register() { + DisplayHandlers.displayHolders.add(this) + } + + fun unRegister() { + DisplayHandlers.displayHolders.remove(this) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt new file mode 100644 index 0000000000..29c5d68831 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt @@ -0,0 +1,27 @@ +package net.horizonsend.ion.server.features.client.display.container + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.miscellaneous.utils.Tasks + +object DisplayHandlers : IonServerComponent() { + val displayHolders = mutableListOf() + + override fun onEnable() { + Tasks.asyncRepeat(100L, 100L, ::runUpdates) + } + + private fun runUpdates() { + displayHolders.removeAll { + val toRemove = !it.isValid() + + if (toRemove) it.removeDisplay() + + toRemove + } + println("Have ${displayHolders.size} handlers") + + for (displayHolder in displayHolders) { + displayHolder.refresh() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt index ed4b50940e..1e18c656fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt @@ -26,6 +26,7 @@ import org.joml.Vector3f import java.util.UUID class TextDisplayHandler( + val holder: DisplayHandlerHolder, val world: World, var x: Double, var y: Double, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt index 1157e9f469..13b6cf3d78 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power +import net.horizonsend.ion.server.features.client.display.container.DisplayHandlerHolder import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -7,11 +8,13 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i /** * Interface providing a simple implementation of a visual display via text display entities. **/ -interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity { - val powerDisplay: TextDisplayHandler - +interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity, DisplayHandlerHolder { override fun updatePowerVisually() { - powerDisplay.setText(formatPower()) + displayHandler.setText(formatPower()) + } + + override fun refresh() { + updatePowerVisually() } companion object { @@ -25,6 +28,7 @@ interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity { val offset = signDirection.direction.multiply(0.39) return TextDisplayHandler( + entity, entity.world, signLoc.x.toDouble() + 0.5 - offset.x, signLoc.y.toDouble() + 0.4, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt index 254ada49cd..ab91fac2ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt @@ -100,21 +100,31 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultibloc override var powerUnsafe: Int, override val maxPower: Int ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { - override val powerDisplay: TextDisplayHandler = createTextDisplayHandler(this) + override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) override fun onLoad() { - powerDisplay.update() - world.ion.multiblockManager.register(this) + + displayHandler.update() + register() } override fun handleRemoval() { world.ion.multiblockManager.deregister(this) - powerDisplay.remove() + + unRegister() + displayHandler.remove() } override fun onUnload() { world.ion.multiblockManager.deregister(this) + + unRegister() + displayHandler.remove() + } + + override fun isValid(): Boolean { + return !removed } override fun storeAdditionalData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 1ec4ba85be..3df462cc3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -107,14 +107,25 @@ abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMu override val maxPower: Int, override var powerUnsafe: Int = 0 ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { - override val powerDisplay: TextDisplayHandler = createTextDisplayHandler(this) + override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) override fun onLoad() { - powerDisplay.update() + register() + displayHandler.update() + } + + override fun onUnload() { + unRegister() + displayHandler.remove() } override fun handleRemoval() { - powerDisplay.remove() + unRegister() + displayHandler.remove() + } + + override fun isValid(): Boolean { + return !removed } override fun storeAdditionalData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt index 2fd56e679b..2df0e7d251 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport -import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ @@ -13,7 +13,7 @@ import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent -object TransportManager : IonServerComponent() { +object TransportManager : SLEventListener() { @EventHandler fun onBlockBreak(event: BlockBreakEvent) { val world = event.block.world diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index d136023079..9a30ca995f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.container.DisplayHandlerHolder import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship @@ -33,7 +34,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandler { +class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandler, DisplayHandlerHolder { constructor(network: PowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction @@ -77,7 +78,13 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl } private fun formatPower(): Component { - val avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) + var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) + + // If no averages, or no power has been moved in 5 seconds, go to 0 + if (averages.isEmpty() || System.currentTimeMillis() - averages.maxOf { it.time } > 5000) { + avg = 0.0 + } + return ofChildren(firstLine, text(avg, GREEN), secondLine) } @@ -105,7 +112,7 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl return sum / timeDiff } - private lateinit var displayHandler: TextDisplayHandler + override lateinit var displayHandler: TextDisplayHandler private fun setupDisplayEntity() { // 95% of the way to the edge of the block once added to the center of the block, to avoid z fighting @@ -118,6 +125,7 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl val z = getZ(facingBlock).toDouble() + 0.5 - offset.z displayHandler = TextDisplayHandler( + this, network.world, x, y, @@ -127,8 +135,18 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl ) } + override fun refresh() { + if (!::displayHandler.isInitialized) return + displayHandler.setText(formatPower()) + } + + override fun isValid(): Boolean { + return !isDead + } + override fun loadIntoNetwork() { setupDisplayEntity() + register() super.loadIntoNetwork() } @@ -140,6 +158,7 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl } override suspend fun handleRemoval(position: BlockKey) { + unRegister() if (::displayHandler.isInitialized) displayHandler.remove() super.handleRemoval(position) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 7e4876dec4..e9687e9307 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.features.client.display.HudIcons import net.horizonsend.ion.server.features.client.display.modular.MultiBlockDisplay import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.type.weapon.sword.SwordListener +import net.horizonsend.ion.server.features.client.display.container.DisplayHandlers import net.horizonsend.ion.server.features.economy.bazaar.Bazaars import net.horizonsend.ion.server.features.economy.bazaar.Merchants import net.horizonsend.ion.server.features.economy.cargotrade.CrateRestrictions @@ -89,7 +90,6 @@ import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCoold import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.features.transport.TransportConfig -import net.horizonsend.ion.server.features.transport.TransportManager import net.horizonsend.ion.server.features.transport.Wires import net.horizonsend.ion.server.features.transport.pipe.Pipes import net.horizonsend.ion.server.features.transport.pipe.filter.Filters @@ -229,7 +229,8 @@ val components: List = listOf( ContactsJammingSidebar, CombatTimer, WorldEditListener, - TransportManager, + TransportManager + DisplayHandlers, PlanetTeleportCooldown, MultiBlockDisplay, ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 6082d19d84..e3d7cc524c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorB import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager +import net.horizonsend.ion.server.features.transport.TransportManager import net.horizonsend.ion.server.features.waypoint.WaypointListeners import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager @@ -83,6 +84,7 @@ val listeners: List = listOf( net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu, RecipeModifications, ActivePlayerController.Companion, + TransportManager, PersonalTransporterManager, // Achievement Listeners From 99bc5227e9d9aa2a53519a648bca4dea06e2a07a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 20:09:33 -0500 Subject: [PATCH 108/500] remove debug from power banks --- .../powerbank/new/NewPowerBankMultiblock.kt | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt index 3df462cc3b..239a79266f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank.new -import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity @@ -8,7 +7,6 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager @@ -16,12 +14,9 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Sign -import org.bukkit.entity.Player -import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataType -abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock, InteractableMultiblock { +abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock { abstract val tierMaterial: Material override val name = "newpowerbank" @@ -84,18 +79,6 @@ abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMu } } - override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { - val world = sign.world - val origin = getOrigin(sign) - - val entity = getMultiblockEntity(world, origin.x, origin.y, origin.z) as PowerBankEntity - - player.information("Entity: $entity") - player.information("Removed: ${entity.removed}") - player.information("Power: ${entity.getPower()}") - player.information("Unsafe Power: ${entity.powerUnsafe}") - } - class PowerBankEntity( manager: ChunkMultiblockManager, multiblock: NewPowerBankMultiblock, From aeaac03ed6ea21273177cd829b54fef648be7613 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 20:15:12 -0500 Subject: [PATCH 109/500] replace old power bank with new, update power cell, simplification --- .../server/features/multiblock/Multiblocks.kt | 18 --- .../newer/MultiblockRegistration.kt | 12 +- .../type/powerbank/PowerBankMultiblock.kt | 80 +++++++++++- .../powerbank/PowerBankMultiblockTier1.kt | 5 +- .../powerbank/PowerBankMultiblockTier2.kt | 5 +- .../powerbank/PowerBankMultiblockTier3.kt | 5 +- .../type/powerbank/PowerCellMultiblock.kt | 23 +++- .../powerbank/new/NewPowerBankMultiblock.kt | 122 ------------------ .../new/NewPowerBankMultiblockTier1.kt | 35 ----- .../new/NewPowerBankMultiblockTier2.kt | 35 ----- .../new/NewPowerBankMultiblockTier3.kt | 35 ----- 11 files changed, 115 insertions(+), 260 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index c74941aa05..18e647d50e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -13,10 +13,6 @@ import net.horizonsend.ion.server.features.achievements.rewardAchievement import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield10 -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield20 -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield30 -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield5 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 @@ -77,7 +73,6 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblo import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock @@ -93,7 +88,6 @@ import net.horizonsend.ion.server.features.multiblock.type.particleshield.Shield import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass30 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass65 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass85 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerCellMultiblock import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier3 @@ -184,11 +178,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(PowerFurnaceMultiblockTier2) registerMultiblock(PowerFurnaceMultiblockTier3) -// registerMultiblock(PowerBankMultiblockTier1) -// registerMultiblock(PowerBankMultiblockTier2) -// registerMultiblock(PowerBankMultiblockTier3) - - registerMultiblock(PowerCellMultiblock) registerMultiblock(ChargerMultiblockTier1) registerMultiblock(ChargerMultiblockTier2) registerMultiblock(ChargerMultiblockTier3) @@ -238,13 +227,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(StandardGravityWellMultiblock) registerMultiblock(AmplifiedGravityWellMultiblock) - registerMultiblock(AreaShield5) - registerMultiblock(AreaShield10) - registerMultiblock(AreaShield20) - registerMultiblock(AreaShield30) - - registerMultiblock(MobDefender) - registerMultiblock(StandardAmmoPressMultiblock) registerMultiblock(AmmoLoaderMultiblock) registerMultiblock(MissileLoaderMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 2351a3e73e..12dd453c0d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -12,9 +12,9 @@ import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield5 import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock -import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.new.NewPowerBankMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier3 import net.horizonsend.ion.server.miscellaneous.utils.multimapOf //TODO store the progress of migrated multiblocks here @@ -37,9 +37,9 @@ object MultiblockRegistration : IonServerComponent() { private fun initMultiblocks() { registerMultiblock(TestMultiblock) - registerMultiblock(NewPowerBankMultiblockTier1) - registerMultiblock(NewPowerBankMultiblockTier2) - registerMultiblock(NewPowerBankMultiblockTier3) + registerMultiblock(PowerBankMultiblockTier1) + registerMultiblock(PowerBankMultiblockTier2) + registerMultiblock(PowerBankMultiblockTier3) registerMultiblock(AreaShield5) registerMultiblock(AreaShield10) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt index fd4e5d747d..04fb57e605 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt @@ -1,14 +1,27 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank +import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType -abstract class PowerBankMultiblock(tierText: String) : Multiblock(), PowerStoringMultiblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock { abstract val tierMaterial: Material override val name = "powerbank" + abstract val maxPower: Int + override val signText = createSignText( line1 = "&2Power &8Bank", line2 = "&4------", @@ -67,4 +80,67 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), PowerStorin } } } + + override fun createEntity( + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + signOffset: BlockFace + ): PowerBankEntity { + return PowerBankEntity( + manager, + this, + x, + y, + z, + world, + signOffset, + maxPower, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + ) + } + + class PowerBankEntity( + manager: ChunkMultiblockManager, + multiblock: Multiblock, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override val maxPower: Int, + override var powerUnsafe: Int = 0 + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { + override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) + + override fun onLoad() { + register() + displayHandler.update() + } + + override fun onUnload() { + unRegister() + displayHandler.remove() + } + + override fun handleRemoval() { + unRegister() + displayHandler.remove() + } + + override fun isValid(): Boolean { + return !removed + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) + } + + override fun toString(): String { + return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $facing" + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt index 4c5246cdd1..2440d72d00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt @@ -2,7 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank import org.bukkit.Material -object PowerBankMultiblockTier1 : PowerBankMultiblock("&7Tier 1") { - override val maxPower = 300_000 +data object PowerBankMultiblockTier1 : PowerBankMultiblock("&7Tier 1") { override val tierMaterial = Material.IRON_BLOCK + + override val maxPower: Int = 100_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt index 3ccf302fc5..f832a25815 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt @@ -2,7 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank import org.bukkit.Material -object PowerBankMultiblockTier2 : PowerBankMultiblock("&eTier 2") { - override val maxPower = 350_000 +data object PowerBankMultiblockTier2 : PowerBankMultiblock("&eTier 2") { override val tierMaterial = Material.GOLD_BLOCK + + override val maxPower: Int = 350_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt index 494b725fe3..c7fa9d9fb6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt @@ -2,7 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank import org.bukkit.Material -object PowerBankMultiblockTier3 : PowerBankMultiblock("&bTier 3") { - override val maxPower = 500_000 +data object PowerBankMultiblockTier3 : PowerBankMultiblock("&bTier 3") { override val tierMaterial = Material.DIAMOND_BLOCK + + override val maxPower: Int = 500_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt index 1c60e9c378..8dc42985e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt @@ -1,10 +1,17 @@ package net.horizonsend.ion.server.features.multiblock.type.powerbank import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataType -object PowerCellMultiblock : Multiblock(), PowerStoringMultiblock { +object PowerCellMultiblock : Multiblock(), PowerStoringMultiblock, EntityMultiblock { override val name = "powercell" override val signText = createSignText( @@ -33,4 +40,18 @@ object PowerCellMultiblock : Multiblock(), PowerStoringMultiblock { } } } + + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): PowerBankMultiblock.PowerBankEntity { + return PowerBankMultiblock.PowerBankEntity( + manager, + this, + x, + y, + z, + world, + signOffset, + 50_000, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + ) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt deleted file mode 100644 index 239a79266f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblock.kt +++ /dev/null @@ -1,122 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank.new - -import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataType - -abstract class NewPowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, SignMultiblock { - abstract val tierMaterial: Material - override val name = "newpowerbank" - - override val signText = createSignText( - line1 = "&2Power &8Bank", - line2 = "&4------", - line3 = null, - line4 = tierText - ) - - override fun MultiblockShape.buildStructure() { - z(+0) { - y(-1) { - x(-1).extractor() - x(+0).wireInputComputer() - x(+1).extractor() - } - - y(+0) { - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - } - - y(+1) { - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - } - } - - z(+1) { - for (i in -1..1) { - y(i) { - x(-1).anyGlass() - x(+0).redstoneBlock() - x(+1).anyGlass() - } - } - } - - z(+2) { - y(-1) { - x(-1).type(tierMaterial) - x(+0).anyGlass() - x(+1).type(tierMaterial) - } - - y(+0) { - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - } - - y(+1) { - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - } - } - } - - class PowerBankEntity( - manager: ChunkMultiblockManager, - multiblock: NewPowerBankMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - override val maxPower: Int, - override var powerUnsafe: Int = 0 - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { - override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) - - override fun onLoad() { - register() - displayHandler.update() - } - - override fun onUnload() { - unRegister() - displayHandler.remove() - } - - override fun handleRemoval() { - unRegister() - displayHandler.remove() - } - - override fun isValid(): Boolean { - return !removed - } - - override fun storeAdditionalData(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) - } - - override fun toString(): String { - return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $facing" - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt deleted file mode 100644 index 0c6bfcea72..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier1.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank.new - -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataType - -data object NewPowerBankMultiblockTier1 : NewPowerBankMultiblock("&7Tier 1") { - override val tierMaterial = Material.IRON_BLOCK - - override fun createEntity( - manager: ChunkMultiblockManager, - data: PersistentMultiblockData, - world: World, - x: Int, - y: Int, - z: Int, - signOffset: BlockFace - ): PowerBankEntity { - return PowerBankEntity( - manager, - this, - x, - y, - z, - world, - signOffset, - 100_000, - data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt deleted file mode 100644 index cef884d22a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier2.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank.new - -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataType - -data object NewPowerBankMultiblockTier2 : NewPowerBankMultiblock("&eTier 2") { - override val tierMaterial = Material.GOLD_BLOCK - - override fun createEntity( - manager: ChunkMultiblockManager, - data: PersistentMultiblockData, - world: World, - x: Int, - y: Int, - z: Int, - signOffset: BlockFace - ): PowerBankEntity { - return PowerBankEntity( - manager, - this, - x, - y, - z, - world, - signOffset, - 350_000, - data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt deleted file mode 100644 index 456621a5d5..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/new/NewPowerBankMultiblockTier3.kt +++ /dev/null @@ -1,35 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank.new - -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataType - -data object NewPowerBankMultiblockTier3 : NewPowerBankMultiblock("&bTier 3") { - override val tierMaterial = Material.DIAMOND_BLOCK - - override fun createEntity( - manager: ChunkMultiblockManager, - data: PersistentMultiblockData, - world: World, - x: Int, - y: Int, - z: Int, - signOffset: BlockFace - ): PowerBankEntity { - return PowerBankEntity( - manager, - this, - x, - y, - z, - world, - signOffset, - 300_000_000, - data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) - ) - } -} From 5c55bafacd304a522c6a3c88406d3994cda1d60d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 20:23:05 -0500 Subject: [PATCH 110/500] Move multis that don't require migration over --- .../server/features/multiblock/Multiblocks.kt | 119 -------------- .../newer/MultiblockRegistration.kt | 152 ++++++++++++++++++ 2 files changed, 152 insertions(+), 119 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 18e647d50e..21b9926bfc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -19,12 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCraft import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock -import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannonBaseMultiblock -import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock -import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 @@ -42,10 +37,6 @@ import net.horizonsend.ion.server.features.multiblock.type.generator.GeneratorMu import net.horizonsend.ion.server.features.multiblock.type.generator.GeneratorMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.gravitywell.AmplifiedGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.gravitywell.StandardGravityWellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass1 -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass2 -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass3 -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass4 import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock @@ -71,23 +62,7 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblo import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced -import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock -import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08Left -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08Right -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08i -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass20 -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass30 -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass65 -import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass85 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier3 @@ -96,40 +71,6 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinter import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CapitalBeamStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.FlamethrowerStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.HorizontalPumpkinCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.MiniPhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.SonicMissileWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIHeavyLaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIPhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.BottomArsenalStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.DownwardRocketStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.HeavyLaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.HorizontalRocketStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.PhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.TopArsenalStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.TorpedoStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.UpwardRocketStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockBottom -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockSide -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockTop -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomHeavyTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomIonTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomLightTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomQuadTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomTriTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopHeavyTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopIonTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopLightTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopQuadTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopTriTurretMultiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys @@ -182,25 +123,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(ChargerMultiblockTier2) registerMultiblock(ChargerMultiblockTier3) - registerMultiblock(HyperdriveMultiblockClass1) - registerMultiblock(HyperdriveMultiblockClass2) - registerMultiblock(HyperdriveMultiblockClass3) - registerMultiblock(HyperdriveMultiblockClass4) - - registerMultiblock(NavigationComputerMultiblockBasic) - registerMultiblock(VerticalNavigationComputerMultiblockAdvanced) - registerMultiblock(HorizontalNavigationComputerMultiblockAdvanced) - - registerMultiblock(ShieldMultiblockClass08Right) - registerMultiblock(ShieldMultiblockClass08Left) - registerMultiblock(ShieldMultiblockClass20) - registerMultiblock(ShieldMultiblockClass30) - registerMultiblock(ShieldMultiblockClass65) - registerMultiblock(ShieldMultiblockClass85) - registerMultiblock(ShieldMultiblockClass08i) - registerMultiblock(BoxShieldMultiblock) - registerMultiblock(EventShieldMultiblock) - registerMultiblock(CarbonProcessorMultiblock) registerMultiblock(CarbonPrinterMultiblock) @@ -231,32 +153,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(AmmoLoaderMultiblock) registerMultiblock(MissileLoaderMultiblock) - registerMultiblock(LaserCannonStarshipWeaponMultiblock) - registerMultiblock(PlasmaCannonStarshipWeaponMultiblock) - registerMultiblock(PulseCannonStarshipWeaponMultiblock) - registerMultiblock(HeavyLaserStarshipWeaponMultiblock) - registerMultiblock(AIHeavyLaserStarshipWeaponMultiblock) - registerMultiblock(AIPhaserStarshipWeaponMultiblock) - registerMultiblock(TorpedoStarshipWeaponMultiblock) - registerMultiblock(PointDefenseStarshipWeaponMultiblockTop) - registerMultiblock(PointDefenseStarshipWeaponMultiblockSide) - registerMultiblock(PointDefenseStarshipWeaponMultiblockBottom) - registerMultiblock(TopLightTurretMultiblock) - registerMultiblock(BottomLightTurretMultiblock) - registerMultiblock(TopHeavyTurretMultiblock) - registerMultiblock(BottomHeavyTurretMultiblock) - registerMultiblock(TopTriTurretMultiblock) - registerMultiblock(BottomTriTurretMultiblock) - registerMultiblock(TopIonTurretMultiblock) - registerMultiblock(BottomIonTurretMultiblock) - registerMultiblock(TopQuadTurretMultiblock) - registerMultiblock(BottomQuadTurretMultiblock) - registerMultiblock(HorizontalRocketStarshipWeaponMultiblock) - registerMultiblock(UpwardRocketStarshipWeaponMultiblock) - registerMultiblock(DownwardRocketStarshipWeaponMultiblock) - registerMultiblock(PhaserStarshipWeaponMultiblock) - registerMultiblock(MiniPhaserStarshipWeaponMultiblock) - registerMultiblock(SonicMissileWeaponMultiblock) registerMultiblock(DecomposerMultiblock) registerMultiblock(DisposalMultiblock) registerMultiblock(MiningLaserMultiblockTier1Top) @@ -271,27 +167,16 @@ object Multiblocks : IonServerComponent() { registerMultiblock(MiningLaserMultiblockTier4Top) registerMultiblock(MiningLaserMultiblockTier4Bottom) registerMultiblock(MiningLaserMultiblockTier4Side) - registerMultiblock(TopArsenalStarshipWeaponMultiblock) - registerMultiblock(BottomArsenalStarshipWeaponMultiblock) registerMultiblock(ItemSplitterMultiblock) registerMultiblock(GasCollectorMultiblock) registerMultiblock(GasPowerPlantMultiblock) registerMultiblock(VentMultiblock) - registerMultiblock(LandingGearMultiblock) - registerMultiblock(AutoCrafterMultiblockTier1) registerMultiblock(AutoCrafterMultiblockTier2) registerMultiblock(AutoCrafterMultiblockTier3) - registerMultiblock(HorizontalPumpkinCannonStarshipWeaponMultiblock) - registerMultiblock(CthulhuBeamStarshipWeaponMultiblockBottom) - registerMultiblock(CthulhuBeamStarshipWeaponMultiblockTop) - registerMultiblock(CthulhuBeamStarshipWeaponMultiblockSide) - registerMultiblock(FlamethrowerStarshipWeaponMultiblock) - registerMultiblock(CapitalBeamStarshipWeaponMultiblock) - registerMultiblock(PlanterMultiblockTier1) registerMultiblock(PlanterMultiblockTier2) registerMultiblock(PlanterMultiblockTier3) @@ -300,10 +185,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(HarvesterMultiblockTier3) registerMultiblock(AntiAirCannonBaseMultiblock) - registerMultiblock(BattleCruiserReactorMultiblock) - registerMultiblock(CruiserReactorMultiblock) - registerMultiblock(BargeReactorMultiBlock) - registerMultiblock(OdometerMultiblock) } private fun registerMultiblock(multiblock: Multiblock) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 12dd453c0d..fb9ebc0957 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -6,15 +6,78 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom +import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide +import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield10 import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield20 import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield30 import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield5 +import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock +import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass1 +import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass2 +import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass3 +import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass4 +import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender +import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock +import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced +import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic +import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced +import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock +import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08Left +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08Right +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08i +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass20 +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass30 +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass65 +import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass85 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerCellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CapitalBeamStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.FlamethrowerStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.HorizontalPumpkinCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.MiniPhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.SonicMissileWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIHeavyLaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIPhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.BottomArsenalStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.DownwardRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.HeavyLaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.HorizontalRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.PhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.TopArsenalStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.TorpedoStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.UpwardRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockBottom +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockSide +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockTop +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomHeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomIonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomLightTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomQuadTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomTriTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopHeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopIonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopLightTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopQuadTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopTriTurretMultiblock import net.horizonsend.ion.server.miscellaneous.utils.multimapOf //TODO store the progress of migrated multiblocks here @@ -37,16 +100,97 @@ object MultiblockRegistration : IonServerComponent() { private fun initMultiblocks() { registerMultiblock(TestMultiblock) + + // Power registerMultiblock(PowerBankMultiblockTier1) registerMultiblock(PowerBankMultiblockTier2) registerMultiblock(PowerBankMultiblockTier3) + registerMultiblock(PowerCellMultiblock) + // Defenses registerMultiblock(AreaShield5) registerMultiblock(AreaShield10) registerMultiblock(AreaShield20) registerMultiblock(AreaShield30) registerMultiblock(MobDefender) + + // Starship weapons + registerMultiblock(LaserCannonStarshipWeaponMultiblock) + registerMultiblock(PlasmaCannonStarshipWeaponMultiblock) + registerMultiblock(PulseCannonStarshipWeaponMultiblock) + registerMultiblock(HeavyLaserStarshipWeaponMultiblock) + registerMultiblock(AIHeavyLaserStarshipWeaponMultiblock) + registerMultiblock(AIPhaserStarshipWeaponMultiblock) + registerMultiblock(TorpedoStarshipWeaponMultiblock) + registerMultiblock(PointDefenseStarshipWeaponMultiblockTop) + registerMultiblock(PointDefenseStarshipWeaponMultiblockSide) + registerMultiblock(PointDefenseStarshipWeaponMultiblockBottom) + registerMultiblock(TopLightTurretMultiblock) + registerMultiblock(BottomLightTurretMultiblock) + registerMultiblock(TopHeavyTurretMultiblock) + registerMultiblock(BottomHeavyTurretMultiblock) + registerMultiblock(TopTriTurretMultiblock) + registerMultiblock(BottomTriTurretMultiblock) + registerMultiblock(TopIonTurretMultiblock) + registerMultiblock(BottomIonTurretMultiblock) + registerMultiblock(TopQuadTurretMultiblock) + registerMultiblock(BottomQuadTurretMultiblock) + registerMultiblock(HorizontalRocketStarshipWeaponMultiblock) + registerMultiblock(UpwardRocketStarshipWeaponMultiblock) + registerMultiblock(DownwardRocketStarshipWeaponMultiblock) + registerMultiblock(PhaserStarshipWeaponMultiblock) + registerMultiblock(MiniPhaserStarshipWeaponMultiblock) + + registerMultiblock(TopArsenalStarshipWeaponMultiblock) + registerMultiblock(BottomArsenalStarshipWeaponMultiblock) + + // Starship event weapons + registerMultiblock(SonicMissileWeaponMultiblock) + registerMultiblock(HorizontalPumpkinCannonStarshipWeaponMultiblock) + registerMultiblock(CthulhuBeamStarshipWeaponMultiblockBottom) + registerMultiblock(CthulhuBeamStarshipWeaponMultiblockTop) + registerMultiblock(CthulhuBeamStarshipWeaponMultiblockSide) + registerMultiblock(FlamethrowerStarshipWeaponMultiblock) + registerMultiblock(CapitalBeamStarshipWeaponMultiblock) + + // Starship utilities + registerMultiblock(BattleCruiserReactorMultiblock) + registerMultiblock(CruiserReactorMultiblock) + registerMultiblock(BargeReactorMultiBlock) + registerMultiblock(FuelTankMultiblock) + + registerMultiblock(OdometerMultiblock) + registerMultiblock(LandingGearMultiblock) + registerMultiblock(MagazineMultiblock) + + registerMultiblock(NavigationComputerMultiblockBasic) + registerMultiblock(VerticalNavigationComputerMultiblockAdvanced) + registerMultiblock(HorizontalNavigationComputerMultiblockAdvanced) + registerMultiblock(HorizontalNavigationComputerMultiblockAdvanced, "NavigationComputerMultiblockAdvanced") + + registerMultiblock(HyperdriveMultiblockClass1) + registerMultiblock(HyperdriveMultiblockClass2) + registerMultiblock(HyperdriveMultiblockClass3) + registerMultiblock(HyperdriveMultiblockClass4) + + // Starship shields + registerMultiblock(ShieldMultiblockClass08Right) + registerMultiblock(ShieldMultiblockClass08Left) + registerMultiblock(ShieldMultiblockClass20) + registerMultiblock(ShieldMultiblockClass30) + registerMultiblock(ShieldMultiblockClass65) + registerMultiblock(ShieldMultiblockClass85) + registerMultiblock(ShieldMultiblockClass08i) + registerMultiblock(BoxShieldMultiblock) + registerMultiblock(EventShieldMultiblock) + + // Misc + registerMultiblock(DisconnectedDockingTubeMultiblock) + registerMultiblock(ConnectedDockingTubeMultiblock) + registerMultiblock(CryoPodMultiblock) + registerMultiblock(AirlockMultiblock) + registerMultiblock(TractorBeamMultiblock) } private fun sortMultiblocks() { @@ -65,6 +209,14 @@ object MultiblockRegistration : IonServerComponent() { multiblocks[name] = multiblock } + private fun registerMultiblock(multiblock: Multiblock, alias: String) { + if (multiblocks.containsKey(alias)) { + throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[alias]}, new: $multiblock") + } + + multiblocks[alias] = multiblock + } + fun getAllMultiblocks() = multiblocks fun getBySignName(name: String): List { From adbd936230c5419a7ecd0cc5873d13b8e890aa47 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 23:19:59 -0500 Subject: [PATCH 111/500] Naming, function standardization --- .../multiblock/entity/MultiblockEntity.kt | 61 +++++++++++----- ...impleTextDisplayPoweredMultiblockEntity.kt | 2 +- .../multiblock/newer/MultiblockAccess.kt | 70 ++++++++----------- .../newer/MultiblockRegistration.kt | 3 + .../multiblock/shape/MultiblockShape.kt | 4 +- .../multiblock/type/SignMultiblock.kt | 4 -- .../multiblock/type/misc/TestMultiblock.kt | 4 +- .../type/powerbank/PowerBankMultiblock.kt | 5 +- .../utils/coordinates/RelativeCoordinates.kt | 12 ++-- 9 files changed, 89 insertions(+), 76 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index a6d3dd9909..6ac485d4c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isBlockLoaded import org.bukkit.Location import org.bukkit.World @@ -16,15 +16,15 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign /** + * @param manager The multiblock manager that this is registered to + * @param multiblock The type of multiblock this entity represents + * * @param x The absolute x position of this multiblock's origin location * @param y The absolute x position of this multiblock's origin location * @param z The absolute x position of this multiblock's origin location - * * @param world The world this multiblock is in * - * @param multiblock The type of multiblock this entity represents - * - * @param facing The direction this multiblock is oriented [from the origin] + * @param structureDirection The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( val manager: ChunkMultiblockManager, @@ -34,7 +34,8 @@ abstract class MultiblockEntity( var y: Int, var z: Int, var world: World, - var facing: BlockFace + + var structureDirection: BlockFace ): PDCSerializable { /** Mark this entity as having been removed */ var removed: Boolean = false @@ -81,14 +82,14 @@ abstract class MultiblockEntity( * This data is serialized and stored on the chunk when not loaded. **/ fun store(): PersistentMultiblockData { - val store = PersistentMultiblockData(x, y, z, multiblock, facing) + val store = PersistentMultiblockData(x, y, z, multiblock, structureDirection) storeAdditionalData(store) return store } fun isSignLoaded(): Boolean { - val signDirection = facing.oppositeFace + val signDirection = structureDirection.oppositeFace val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) return isBlockLoaded(world, signLoc.x, signLoc.y, signLoc.z) @@ -98,25 +99,47 @@ abstract class MultiblockEntity( * Gets the sign of this multiblock **/ fun getSign(): Sign? { - val signDirection = facing.oppositeFace - val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) - - return getBlockIfLoaded(world, signLoc.x, signLoc.y, signLoc.z)?.state as? Sign + return getSignFromOrigin(world,vec3i, structureDirection).state as? Sign } - fun isIntact(): Boolean = multiblock.blockMatchesStructure( - world.getBlockAt(x, y, z), - facing.oppositeFace, - loadChunks = false, - particles = false - ) + /** + * + **/ + fun isIntact(checkSign: Boolean = true): Boolean { + if (checkSign && getSign() == null) return false + + return multiblock.blockMatchesStructure( + world.getBlockAt(x, y, z), + structureDirection, + loadChunks = false, + particles = false + ) + } /** * **/ fun getBlockRelative(backFourth: Int, leftRight: Int, upDown: Int): Block { - val (x, y, z) = getRelative(vec3i, facing.oppositeFace, backFourth, leftRight, upDown) + val (x, y, z) = getRelative(vec3i, structureDirection, backFourth, leftRight, upDown) return world.getBlockAt(x, y, z) } + + companion object { + /** Get the multiblock's origin from its sign */ + fun getOriginFromSign(sign: Sign): Block { + val multiblockDirection = sign.getFacing().oppositeFace + + return sign.block.getRelative(multiblockDirection) + } + + /** Get the sign position from a multiblock's orientation and origin */ + fun getSignFromOrigin(origin: Block, structureDirection: BlockFace): Block = origin.getRelative(structureDirection.oppositeFace) + + /** Get the sign position from a multiblock's orientation and origin */ + fun getSignFromOrigin(world: World, origin: Vec3i, structureDirection: BlockFace): Block { + val position = origin.getRelative(structureDirection.oppositeFace) + return world.getBlockAt(position.x, position.y, position.z) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt index 13b6cf3d78..12fc21b1fb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt @@ -21,7 +21,7 @@ interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity, Di fun createTextDisplayHandler(entity: SimpleTextDisplayPoweredMultiblockEntity): TextDisplayHandler { require(entity is MultiblockEntity) - val signDirection = entity.facing.oppositeFace + val signDirection = entity.structureDirection.oppositeFace val signLoc = Vec3i(entity.x, entity.y, entity.z) + Vec3i(signDirection.modX, 0, signDirection.modZ) // 70% of the way through the block diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 6afa6a52df..9c011be86f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -11,9 +11,9 @@ import net.horizonsend.ion.common.utils.text.subStringBetween import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.getMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.removeMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.SignMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK @@ -27,7 +27,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isSign import org.bukkit.World -import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player @@ -143,7 +142,7 @@ object MultiblockAccess : IonServerComponent() { } } - val origin = sign.getMultiblockOrigin() + val origin = MultiblockEntity.getOriginFromSign(sign) return getMultiblock(sign.world, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace, checkStructure, loadChunks) } @@ -152,25 +151,22 @@ object MultiblockAccess : IonServerComponent() { * * @return if the multiblock could be created properly. **/ - fun setMultiblock(detector: Player, world: World, x: Int, y: Int, z: Int, face: BlockFace, multiblock: Multiblock): Boolean { - if (multiblock is SignMultiblock) { - val signOffset = face.oppositeFace - val signLoc = Vec3i(x, y, z).getRelative(signOffset) - val sign = getBlockIfLoaded(world, signLoc.x, signLoc.y, signLoc.z)?.state as? Sign ?: return false + fun setMultiblock(detector: Player, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace, multiblock: Multiblock): Boolean { + val signBlock = MultiblockEntity.getSignFromOrigin(world, Vec3i(x, y, z), structureDirection) + val sign = signBlock.state as? Sign ?: return false - Tasks.sync { - sign.persistentDataContainer.set( - MULTIBLOCK, - STRING, - multiblock.javaClass.simpleName - ) + Tasks.sync { + sign.persistentDataContainer.set( + MULTIBLOCK, + STRING, + multiblock.javaClass.simpleName + ) - sign.isWaxed = true + sign.isWaxed = true - multiblock.setupSign(detector, sign) + multiblock.setupSign(detector, sign) - sign.update(false, false) - } + sign.update(false, false) } if (multiblock is EntityMultiblock<*>) { @@ -184,7 +180,7 @@ object MultiblockAccess : IonServerComponent() { val chunkZ = z.shr(4) world.ion.getChunk(chunkX, chunkZ)?.let { - it.region.launch { it.multiblockManager.addNewMultiblockEntity(multiblock, x, y, z, face) } + it.region.launch { it.multiblockManager.addNewMultiblockEntity(multiblock, x, y, z, structureDirection) } } } @@ -194,9 +190,13 @@ object MultiblockAccess : IonServerComponent() { /** * Remove this multiblock & entity, provided the multiblock origin **/ - fun removeMultiblock(world: World, x: Int, y: Int, z: Int, facing: BlockFace): Multiblock? { + fun removeMultiblock(world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): Multiblock? { + val existing = getMultiblockEntity(world, x, y, z) + // Ensure that the removal additional signs placed on the sides of an origin don't remove the entity + if (existing?.structureDirection != structureDirection) return null + val removed = removeMultiblockEntity(world, x, y, z) - multiblockCache[world]?.invalidate(Vec3i(x, y, z) to facing) + multiblockCache[world]?.invalidate(Vec3i(x, y, z) to structureDirection) return removed?.multiblock } @@ -205,8 +205,7 @@ object MultiblockAccess : IonServerComponent() { * * @return the detected multiblock, if found **/ - fun tryDetectMultiblock(player: Player, sign: Sign, loadChunks: Boolean = false): Multiblock? { - val signLoc = Vec3i(sign.location) + fun tryDetectMultiblock(player: Player, sign: Sign, face: BlockFace? = null, loadChunks: Boolean = false): Multiblock? { val world = sign.world val blankText = sign.front().line(0).plainText() @@ -215,8 +214,7 @@ object MultiblockAccess : IonServerComponent() { val direction = sign.getFacing().oppositeFace // Get the block that the sign is placed on - val originBlock = signLoc.getRelative(direction, 1) - val (x, y, z) = originBlock + val originBlock = MultiblockEntity.getOriginFromSign(sign) // Possible multiblocks from the sign val possible = MultiblockRegistration.getBySignName(name) @@ -225,10 +223,10 @@ object MultiblockAccess : IonServerComponent() { val found = computeMultiblockAtLocation( world, - x, - y, - z, - null, + originBlock.x, + originBlock.y, + originBlock.z, + face, loadChunks = loadChunks, restrictedList = possible ) @@ -241,7 +239,7 @@ object MultiblockAccess : IonServerComponent() { return null } - setMultiblock(player, world, x, y, z, direction, found) + setMultiblock(player, world, originBlock.x, originBlock.y, originBlock.z, direction, found) return found } @@ -261,11 +259,9 @@ object MultiblockAccess : IonServerComponent() { if (sign.persistentDataContainer.has(MULTIBLOCK)) return - val result = tryDetectMultiblock(event.player, sign, false) + val result = tryDetectMultiblock(event.player, sign, face = sign.getFacing().oppositeFace, loadChunks = false) ?: return - if (result != null) { - event.player.success("Detected new ${result.name}") - } + event.player.success("Detected new ${result.name}") } @EventHandler @@ -273,14 +269,10 @@ object MultiblockAccess : IonServerComponent() { if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return val sign = event.block.state as? Sign ?: return - val origin = sign.getMultiblockOrigin() + val origin = MultiblockEntity.getOriginFromSign(sign) val removed = removeMultiblock(event.block.world, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) ?: return event.player.information("Destroyed ${removed.name}") } - - fun Sign.getMultiblockOrigin(): Block { - return block.getRelative(getFacing().oppositeFace, 1) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index fb9ebc0957..5be26a6811 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -105,6 +105,9 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(PowerBankMultiblockTier1) registerMultiblock(PowerBankMultiblockTier2) registerMultiblock(PowerBankMultiblockTier3) + registerMultiblock(PowerBankMultiblockTier1, "NewPowerBankMultiblockTier1") //TODO testing only - remove on live + registerMultiblock(PowerBankMultiblockTier2, "NewPowerBankMultiblockTier2") //TODO testing only - remove on live + registerMultiblock(PowerBankMultiblockTier3, "NewPowerBankMultiblockTier3") //TODO testing only - remove on live registerMultiblock(PowerCellMultiblock) // Defenses diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index c0ccb27a0d..79949b7337 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -250,11 +250,11 @@ class MultiblockShape { } CARDINAL_BLOCK_FACES.forEach { inwardFace -> - val intTrio = toAbsolute(inwardFace, inward, right, upward) + val vec = toAbsolute(inwardFace, inward, right, upward) val requirementMap = getRequirementMap(inwardFace) - requirementMap[intTrio] = requirement + requirementMap[vec] = requirement } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt deleted file mode 100644 index 0a1bb4b068..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/SignMultiblock.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type - -interface SignMultiblock { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 284a929985..4a0b198b7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -74,7 +74,7 @@ object TestMultiblock : Multiblock(), EntityMultiblock, SignMultiblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock { abstract val tierMaterial: Material override val name = "powerbank" @@ -140,7 +139,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMulti } override fun toString(): String { - return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $facing" + return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $structureDirection" } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt index 213db71bf3..43b3d41bb4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt @@ -3,18 +3,18 @@ package net.horizonsend.ion.server.miscellaneous.utils.coordinates import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.block.BlockFace -fun toAbsolute(inwardFace: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { - val rightFace = inwardFace.rightFace +fun toAbsolute(forwardFace: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { + val rightFace = forwardFace.rightFace return Vec3i( - x = rightFace.modX * leftRight + inwardFace.modX * backFourth, + x = rightFace.modX * leftRight + forwardFace.modX * backFourth, y = upDown, - z = rightFace.modZ * leftRight + inwardFace.modZ * backFourth + z = rightFace.modZ * leftRight + forwardFace.modZ * backFourth ) } -fun getRelative(origin: Vec3i, face: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { - val relative = toAbsolute(face, backFourth, leftRight, upDown) +fun getRelative(origin: Vec3i, forwardFace: BlockFace, forward: Int, right: Int, up: Int): Vec3i { + val relative = toAbsolute(forwardFace, forward, right, up) return origin + relative } From 9746a749a1c39de603a94d942792ad85db613e10 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 28 Aug 2024 23:47:14 -0500 Subject: [PATCH 112/500] more cleaning, add built in alternate sign names --- .../server/features/multiblock/Multiblock.kt | 1 + .../{type/crafting => }/MultiblockRecipes.kt | 0 .../multiblock/newer/MultiblockAccess.kt | 20 ++++++++- .../newer/MultiblockRegistration.kt | 18 ++++---- .../multiblock/type/FurnaceMultiblock.kt | 2 +- .../multiblock/type/InteractableMultiblock.kt | 41 ------------------- .../miscellaneous/registrations/Components.kt | 3 +- .../miscellaneous/registrations/Listeners.kt | 4 +- 8 files changed, 33 insertions(+), 56 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{type/crafting => }/MultiblockRecipes.kt (100%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 2e2c608e8a..4c9a43dc99 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -21,6 +21,7 @@ import org.bukkit.entity.Player abstract class Multiblock { abstract val name: String + open val alternativeDetectionNames: Array = arrayOf() abstract val signText: Array diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRecipes.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/crafting/MultiblockRecipes.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRecipes.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 9c011be86f..97434ee869 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.getMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.removeMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK @@ -217,7 +218,7 @@ object MultiblockAccess : IonServerComponent() { val originBlock = MultiblockEntity.getOriginFromSign(sign) // Possible multiblocks from the sign - val possible = MultiblockRegistration.getBySignName(name) + val possible = MultiblockRegistration.getByDetectionName(name) if (possible.isEmpty()) return null @@ -257,13 +258,28 @@ object MultiblockAccess : IonServerComponent() { val clickedBlock = event.clickedBlock ?: return val sign = clickedBlock.state as? Sign ?: return - if (sign.persistentDataContainer.has(MULTIBLOCK)) return + if (sign.persistentDataContainer.has(MULTIBLOCK)) { + checkInteractable(sign, event) + return + } val result = tryDetectMultiblock(event.player, sign, face = sign.getFacing().oppositeFace, loadChunks = false) ?: return event.player.success("Detected new ${result.name}") } + fun checkInteractable(sign: Sign, event: PlayerInteractEvent) { + // Quick check + val multiblockType = getFast(sign) + if (multiblockType !is InteractableMultiblock) return + + // Check structure + val origin = MultiblockEntity.getOriginFromSign(sign) + if (!multiblockType.blockMatchesStructure(origin, sign.getFacing().oppositeFace)) return + + multiblockType.onSignInteract(sign, event.player, event) + } + @EventHandler fun onPlayerBreakBlock(event: BlockBreakEvent) { if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 5be26a6811..10cde2502a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -1,9 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.newer import com.google.common.collect.Multimap -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom @@ -80,10 +77,9 @@ import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopTriTurretMultiblock import net.horizonsend.ion.server.miscellaneous.utils.multimapOf -//TODO store the progress of migrated multiblocks here object MultiblockRegistration : IonServerComponent() { private val multiblocks: MutableMap = mutableMapOf() - private val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) + /** * The multiblocks grouped by their sign text. * @@ -197,8 +193,14 @@ object MultiblockRegistration : IonServerComponent() { } private fun sortMultiblocks() { - for ((_, multi) in getAllMultiblocks()) { + for (multi in getAllMultiblocks()) { byDetectionName[multi.name].add(multi) + + if (multi.alternativeDetectionNames.isEmpty()) continue + + for (altName in multi.alternativeDetectionNames) { + byDetectionName[multi.name].add(multi) + } } } @@ -220,9 +222,9 @@ object MultiblockRegistration : IonServerComponent() { multiblocks[alias] = multiblock } - fun getAllMultiblocks() = multiblocks + fun getAllMultiblocks() = multiblocks.values.toSet() - fun getBySignName(name: String): List { + fun getByDetectionName(name: String): List { return byDetectionName[name].toList() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt index 1e8b071724..dc6767d73f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceEventHandler -import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt index 9181e215dc..f284bf9a85 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/InteractableMultiblock.kt @@ -1,50 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type -import kotlinx.coroutines.launch -import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess -import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState -import net.horizonsend.ion.server.listener.SLEventListener import org.bukkit.block.Sign import org.bukkit.entity.Player -import org.bukkit.event.EventHandler -import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.EquipmentSlot interface InteractableMultiblock { fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) - - companion object : SLEventListener() { - @EventHandler - fun onPlayerInteract(event: PlayerInteractEvent) = Multiblocks.multiblockCoroutineScope.launch { - if (event.hand != EquipmentSlot.HAND) return@launch - if (event.action != Action.RIGHT_CLICK_BLOCK) return@launch - val player = event.player - - val clickedBlock = event.clickedBlock ?: return@launch - val sign = getBukkitBlockState(clickedBlock, false) as? Sign ?: return@launch - - val multiblock = Multiblocks.getFromSignPosition( - sign.world, - sign.x, - sign.y, - sign.z, - checkStructure = true, - loadChunks = false - ) ?: MultiblockAccess.getMultiblock(sign, checkStructure = true, loadChunks = false) - - if (multiblock !is InteractableMultiblock) return@launch - - multiblock.requiredPermission?.let { permission -> - if (!player.hasPermission(permission)) { - player.userError("You don't have permission to use that multiblock!") - return@launch - } - } - - multiblock.onSignInteract(sign, player, event) - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index e9687e9307..d79350e2d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -37,6 +37,7 @@ import net.horizonsend.ion.server.features.misc.GameplayTweaks import net.horizonsend.ion.server.features.misc.ProxyMessaging import net.horizonsend.ion.server.features.misc.Shuttles import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge +import net.horizonsend.ion.server.features.multiblock.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration @@ -229,7 +230,7 @@ val components: List = listOf( ContactsJammingSidebar, CombatTimer, WorldEditListener, - TransportManager + TransportManager, DisplayHandlers, PlanetTeleportCooldown, MultiBlockDisplay, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index e3d7cc524c..0842cf719e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -7,9 +7,8 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemListeners import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporterManager import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners import net.horizonsend.ion.server.features.machine.CryoPods -import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam +import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager @@ -55,7 +54,6 @@ val listeners: List = listOf( EntityListener, FurnaceListener, InteractListener, - InteractableMultiblock, InventoryListener, BowHitListener, From 57a83acc325d937b451806f5f0303ffa6f6e3c70 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 29 Aug 2024 00:49:47 -0500 Subject: [PATCH 113/500] basic piped resource registration, add gasses --- .../ion/server/features/gas/Gasses.kt | 44 ++++++++++++------- .../ion/server/features/gas/type/Gas.kt | 5 ++- .../ion/server/features/gas/type/GasFuel.kt | 4 +- .../server/features/gas/type/GasOxidizer.kt | 4 +- .../multiblock/newer/MultiblockAccess.kt | 2 +- .../server/features/transport/fluids/Fluid.kt | 4 ++ .../transport/fluids/TransportedFluids.kt | 29 ++++++++++++ .../fluids/properties/FluidProperty.kt | 4 ++ .../transport/fluids/types/BasicFluid.kt | 6 +++ .../transport/fluids/types/GasFluid.kt | 11 +++++ .../miscellaneous/registrations/Components.kt | 2 + 11 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidProperty.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt index 17ce070c99..95a500b749 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt @@ -8,92 +8,102 @@ import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.type.Gas import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Location import org.bukkit.inventory.ItemStack +import java.util.concurrent.ThreadLocalRandom +import java.util.function.Supplier @Suppress("UNUSED") object Gasses : IonServerComponent(false) { private val gasses = mutableMapOf() // Fuels - val HYDROGEN = registerGas( + val HYDROGEN: GasFuel = registerGas( object : GasFuel( identifier = "HYDROGEN", displayName = text("Hydrogen", NamedTextColor.RED), containerIdentifier = "GAS_CANISTER_HYDROGEN", powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.cooldown, - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::hydrogen + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::hydrogen, + transportedFluidSupplier = Supplier { TransportedFluids.HYDROGEN } ) {} ) - val NITROGEN = registerGas( + val NITROGEN: GasFuel = registerGas( object : GasFuel( identifier = "NITROGEN", displayName = text("Nitrogen", NamedTextColor.RED), containerIdentifier = "GAS_CANISTER_NITROGEN", powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.cooldown, - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::nitrogen + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::nitrogen, + transportedFluidSupplier = { TransportedFluids.NITROGEN } ) {} ) - val METHANE = registerGas( + val METHANE: GasFuel = registerGas( object : GasFuel( identifier = "METHANE", displayName = text("Methane", NamedTextColor.RED), containerIdentifier = "GAS_CANISTER_METHANE", powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.methane.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.methane.cooldown, - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::methane + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::methane, + transportedFluidSupplier = { TransportedFluids.METHANE } ) {} ) // Oxidizers - val OXYGEN = registerGas( + val OXYGEN: GasOxidizer = registerGas( object : GasOxidizer( identifier = "OXYGEN", displayName = text("Oxygen", NamedTextColor.YELLOW), containerIdentifier = "GAS_CANISTER_OXYGEN", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.oxygen.powerMultiplier, - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::oxygen + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::oxygen, + transportedFluidSupplier = { TransportedFluids.OXYGEN } ) {} ) - val CHLORINE = registerGas( + val CHLORINE: GasOxidizer = registerGas( object : GasOxidizer( identifier = "CHLORINE", displayName = text("Chlorine", NamedTextColor.YELLOW), containerIdentifier = "GAS_CANISTER_CHLORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.chlorine.powerMultiplier, - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::chlorine + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::chlorine, + transportedFluidSupplier = { TransportedFluids.CHLORINE } ) {} ) - val FLUORINE = registerGas( + val FLUORINE: GasOxidizer = registerGas( object : GasOxidizer( identifier = "FLUORINE", displayName = text("Fluorine", NamedTextColor.YELLOW), containerIdentifier = "GAS_CANISTER_FLUORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.fluorine.powerMultiplier, - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::fluorine + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::fluorine, + transportedFluidSupplier = { TransportedFluids.FLUORINE } ) {} ) // Other - val HELIUM = registerGas( + val HELIUM: Gas = registerGas( object : Gas( identifier = "HELIUM", displayName = text("Helium", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_HELIUM", - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::helium + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::helium, + transportedFluidSupplier = { TransportedFluids.HELIUM } ) {} ) - val CARBON_DIOXIDE = registerGas( - object : Gas( + val CARBON_DIOXIDE: Gas = registerGas(object : Gas( identifier = "CARBON_DIOXIDE", displayName = text("Carbon Dioxide", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_CARBON_DIOXIDE", - configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::carbonDioxide + configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::carbonDioxide, + transportedFluidSupplier = { TransportedFluids.CARBON_DIOXIDE } ) {} ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt index be6b338845..f9d6e8320b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses import net.horizonsend.ion.server.features.gas.collection.Factor +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.kyori.adventure.text.Component import org.bukkit.World @@ -12,9 +13,11 @@ abstract class Gas( val displayName: Component, val containerIdentifier: String, - private val configurationSupplier: Supplier + private val configurationSupplier: Supplier, + private val transportedFluidSupplier: Supplier ) { val configuration get() = configurationSupplier.get() + val fluid get() = transportedFluidSupplier.get() private fun getFactors(world: World): Factor? { val ion = world.ion diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt index 0e46002755..f595fa068c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid import net.kyori.adventure.text.Component import java.util.function.Supplier @@ -9,8 +10,9 @@ abstract class GasFuel( displayName: Component, containerIdentifier: String, configurationSupplier: Supplier, + transportedFluidSupplier: Supplier, val powerPerUnit: Int, val cooldown: Int -) : Gas(identifier, displayName, containerIdentifier, configurationSupplier) +) : Gas(identifier, displayName, containerIdentifier, configurationSupplier, transportedFluidSupplier) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt index ada252d2cb..9ff3ab57f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid import net.kyori.adventure.text.Component import java.util.function.Supplier @@ -9,6 +10,7 @@ abstract class GasOxidizer( displayName: Component, containerIdentifier: String, configurationSupplier: Supplier, + transportedFluidSupplier: Supplier, val powerMultiplier: Double -) : Gas(identifier, displayName, containerIdentifier, configurationSupplier) +) : Gas(identifier, displayName, containerIdentifier, configurationSupplier, transportedFluidSupplier) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt index 97434ee869..b3bef506a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt @@ -90,7 +90,7 @@ object MultiblockAccess : IonServerComponent() { z: Int, face: BlockFace?, loadChunks: Boolean = false, - restrictedList: Collection = MultiblockRegistration.getAllMultiblocks().values + restrictedList: Collection = MultiblockRegistration.getAllMultiblocks() ): Multiblock? { // Will only return null if not loaded and don't load chunks val originBlock = if (loadChunks) world.getBlockAt(x, y, z) else getBlockIfLoaded(world, x, y, z) ?: return null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt new file mode 100644 index 0000000000..9264cccf3a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.fluids + +abstract class Fluid { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt new file mode 100644 index 0000000000..7e31bad92f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt @@ -0,0 +1,29 @@ +package net.horizonsend.ion.server.features.transport.fluids + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.gas.Gasses +import net.horizonsend.ion.server.features.transport.fluids.types.BasicFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid + +// +object TransportedFluids : IonServerComponent() { + val HYDROGEN = register(GasFluid { Gasses.HYDROGEN }) + val NITROGEN = register(GasFluid { Gasses.NITROGEN }) + val METHANE = register(GasFluid { Gasses.METHANE }) + val OXYGEN = register(GasFluid { Gasses.OXYGEN }) + val CHLORINE = register(GasFluid { Gasses.CHLORINE }) + val FLUORINE = register(GasFluid { Gasses.FLUORINE }) + val HELIUM = register(GasFluid { Gasses.FLUORINE }) + val CARBON_DIOXIDE = register(GasFluid { Gasses.FLUORINE }) + + private val fluids = mutableListOf() + + fun register(fluid: T): T { + fluids.add(fluid) + return fluid + } + + fun registerBasic(): BasicFluid { + throw NotImplementedError() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidProperty.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidProperty.kt new file mode 100644 index 0000000000..44afb2bd8f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidProperty.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.fluids.properties + +interface FluidProperty { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt new file mode 100644 index 0000000000..45e2ebe217 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.fluids.types + +import net.horizonsend.ion.server.features.transport.fluids.Fluid + +class BasicFluid : Fluid() { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt new file mode 100644 index 0000000000..3e323591b2 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.transport.fluids.types + +import net.horizonsend.ion.server.features.gas.type.Gas +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import java.util.function.Supplier + +class GasFluid( + private val gasSupplier: Supplier +) : Fluid() { + val gas get() = gasSupplier.get() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index d79350e2d2..8a4a876ac8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -92,6 +92,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShi import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.features.transport.TransportConfig import net.horizonsend.ion.server.features.transport.Wires +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids import net.horizonsend.ion.server.features.transport.pipe.Pipes import net.horizonsend.ion.server.features.transport.pipe.filter.Filters import net.horizonsend.ion.server.features.tutorial.Tutorials @@ -164,6 +165,7 @@ val components: List = listOf( ShipmentManager, Gasses, + TransportedFluids, Bazaars, Merchants, From 5d7483c9a4738861ec0495e98f9abf6ab31f086b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 29 Aug 2024 02:30:55 -0500 Subject: [PATCH 114/500] Fluid storing entity setup, piped gas collector structure --- .../server/command/misc/MultiblockCommand.kt | 12 +- .../ion/server/features/gas/type/Gas.kt | 4 +- .../ion/server/features/gas/type/GasFuel.kt | 4 +- .../server/features/gas/type/GasOxidizer.kt | 4 +- .../CategoryRestrictedInternalStorage.kt | 20 +++ .../entity/type/fluids/FluidStoringEntity.kt | 13 ++ .../entity/type/fluids/InternalStorage.kt | 50 ++++++++ .../type/fluids/UnlimitedInternalStorage.kt | 17 +++ .../multiblock/newer/MultiblockEntities.kt | 5 + .../newer/MultiblockRegistration.kt | 4 + .../multiblock/shape/MultiblockShape.kt | 17 ++- .../type/ammo/AmmoLoaderMultiblock.kt | 12 +- .../type/ammo/AmmoPressMultiblock.kt | 8 +- .../multiblock/type/areashield/AreaShield.kt | 4 +- .../type/gas/GasPowerPlantMultiblock.kt | 32 ++--- .../type/gas/PipedGasCollectorMultiblock.kt | 115 ++++++++++++++++++ .../type/industry/CentrifugeMultiblock.kt | 12 +- .../multiblock/type/misc/MobDefender.kt | 4 +- .../multiblock/type/misc/TestMultiblock.kt | 4 +- .../type/powerbank/PowerBankMultiblock.kt | 8 +- .../type/powerbank/PowerCellMultiblock.kt | 4 +- .../type/printer/PrinterMultiblock.kt | 12 +- .../type/starshipweapon/EntityMultiblock.kt | 23 ++-- .../CapitalBeamStarshipWeaponMultiblock.kt | 56 ++++----- .../PumpkinCannonStarshipWeaponMultiblock.kt | 16 +-- .../heavy/AIPhaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/PhaserStarshipWeaponMultiblock.kt | 2 +- .../turret/IonTurretMultiblock.kt | 6 +- .../server/features/transport/fluids/Fluid.kt | 4 - .../features/transport/fluids/PipedFluid.kt | 7 ++ .../transport/fluids/TransportedFluids.kt | 32 +++-- .../fluids/properties/FluidCategory.kt | 13 ++ .../transport/fluids/types/BasicFluid.kt | 6 - .../transport/fluids/types/BasicPipedFluid.kt | 4 + .../transport/fluids/types/GasFluid.kt | 11 -- .../transport/fluids/types/GasPipedFluid.kt | 14 +++ 36 files changed, 411 insertions(+), 150 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 432ba1ddee..d8cf6128f1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -10,15 +10,15 @@ import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.bracketed +import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.displayBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.kyori.adventure.text.Component import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.format.NamedTextColor @@ -32,19 +32,19 @@ import org.bukkit.util.Vector @CommandAlias("multiblock") @CommandPermission("ion.multiblock") -object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { +object MultiblockCommand : SLCommand() { override fun onEnable(manager: PaperCommandManager) { manager.commandContexts.registerContext(Multiblock::class.java) { c: BukkitCommandExecutionContext -> val name: String = c.popFirstArg() - Multiblocks.all().firstOrNull { it.javaClass.simpleName == name } + MultiblockRegistration.getAllMultiblocks().firstOrNull { it.javaClass.simpleName == name } ?: throw InvalidCommandArgument("Multiblock $name not found!") } registerStaticCompletion( manager, "multiblocks", - Multiblocks.all().joinToString("|") { it.javaClass.simpleName }) + MultiblockRegistration.getAllMultiblocks().joinToString("|") { it.javaClass.simpleName }) } /** @@ -53,7 +53,7 @@ object MultiblockCommand : net.horizonsend.ion.server.command.SLCommand() { fun setupCommand(player: Player, sign: Sign, lastMatch: Multiblock) { val multiblockType = lastMatch.name - val possibleTiers = Multiblocks.all().filter { it.name == multiblockType } + val possibleTiers = MultiblockRegistration.getAllMultiblocks().filter { it.name == multiblockType } if (possibleTiers.size == 1) { onCheck(player, possibleTiers.first(), sign.x, sign.y, sign.z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt index f9d6e8320b..db7beea7a0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses import net.horizonsend.ion.server.features.gas.collection.Factor -import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.kyori.adventure.text.Component import org.bukkit.World @@ -14,7 +14,7 @@ abstract class Gas( val containerIdentifier: String, private val configurationSupplier: Supplier, - private val transportedFluidSupplier: Supplier + private val transportedFluidSupplier: Supplier ) { val configuration get() = configurationSupplier.get() val fluid get() = transportedFluidSupplier.get() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt index f595fa068c..e3792c8209 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses -import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid import net.kyori.adventure.text.Component import java.util.function.Supplier @@ -10,7 +10,7 @@ abstract class GasFuel( displayName: Component, containerIdentifier: String, configurationSupplier: Supplier, - transportedFluidSupplier: Supplier, + transportedFluidSupplier: Supplier, val powerPerUnit: Int, val cooldown: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt index 9ff3ab57f0..a04e2d88c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses -import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid import net.kyori.adventure.text.Component import java.util.function.Supplier @@ -10,7 +10,7 @@ abstract class GasOxidizer( displayName: Component, containerIdentifier: String, configurationSupplier: Supplier, - transportedFluidSupplier: Supplier, + transportedFluidSupplier: Supplier, val powerMultiplier: Double ) : Gas(identifier, displayName, containerIdentifier, configurationSupplier, transportedFluidSupplier) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt new file mode 100644 index 0000000000..d4123d09f2 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory + +class CategoryRestrictedInternalStorage( + private val storageCapacity: Int, + private vararg val allowedCategories: FluidCategory +) : InternalStorage() { + override fun getCapacity(): Int = storageCapacity + + override fun canStore(resource: PipedFluid, liters: Double): Boolean { + if (liters + getAmount() > getCapacity()) return false + + // Check that the fluid attempting to be stored is the same as the one currently stored + if (getStoredFluid() != null && resource != getStoredFluid()) return false + + return allowedCategories.intersect(resource.categories.toSet()).isNotEmpty() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt new file mode 100644 index 0000000000..3bbd0ff2a7 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +interface FluidStoringEntity { + val capacities: Array + + fun canStore(fluid: PipedFluid, amount: Double) = capacities.any { it.canStore(fluid, amount) } + + fun firstCasStore(fluid: PipedFluid, amount: Double): InternalStorage? = capacities.firstOrNull { it.canStore(fluid, amount) } + + fun getStoredResources() : Map = capacities.associate { it.getStoredFluid() to it.getAmount().toDouble() } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt new file mode 100644 index 0000000000..6977a48e88 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt @@ -0,0 +1,50 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +/** + * Fluid storing multiblocks can have a single, or multiple fluid storage capacities + * + * Each internal storage can hold a single type of fluid + **/ +abstract class InternalStorage { + protected var amountUnsafe: Int = 0 + protected var fluidUnsafe: PipedFluid? = null + + abstract fun canStore(resource: PipedFluid, liters: Double): Boolean + + abstract fun getCapacity(): Int + + fun getStoredFluid(): PipedFluid? = fluidUnsafe + + fun addAmount(amount: Int) { + setAmount(getAmount() + amount) + } + + fun getAmount(): Int = amountUnsafe + + fun setContents(fluid: PipedFluid, amount: Int) { + setFluid(fluid) + setAmount(amount) + } + + fun setAmount(amount: Int) { + val corrected = amount.coerceIn(0, getCapacity()) + + this.amountUnsafe = corrected + + if (corrected == 0) setFluid(null) + + updateVisually() + } + + fun setFluid(fluid: PipedFluid?) { + this.fluidUnsafe = fluid + + updateVisually() + } + + open fun updateVisually() {} + + fun getContents(): Pair = fluidUnsafe to getAmount() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt new file mode 100644 index 0000000000..5a092735c5 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt @@ -0,0 +1,17 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +/** + * Internal storage with no limits on what fluid can be stored + **/ +class UnlimitedInternalStorage(private val storageCapacity: Int) : InternalStorage() { + override fun getCapacity(): Int = storageCapacity + + override fun canStore(resource: PipedFluid, liters: Double): Boolean { + if (liters + getAmount() > getCapacity()) return false + + // Check that the fluid attempting to be stored is the same as the one currently stored + return !(getStoredFluid() != null && resource != getStoredFluid()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt index 291ae93b7b..d181b33535 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManag import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import org.bukkit.World +import org.bukkit.block.Block object MultiblockEntities { /** @@ -16,6 +17,10 @@ object MultiblockEntities { return ionChunk.multiblockManager[x, y, z] } + fun getMultiblockEntity(origin: Block): MultiblockEntity? { + return getMultiblockEntity(origin.world, origin.x, origin.y, origin.z) + } + /** * Add a new multiblock entity to the chunk **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 10cde2502a..628bdc821d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruis import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.gas.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass1 import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass2 import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass3 @@ -106,6 +107,9 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(PowerBankMultiblockTier3, "NewPowerBankMultiblockTier3") //TODO testing only - remove on live registerMultiblock(PowerCellMultiblock) + // Gas + registerMultiblock(PipedGasCollectorMultiblock) + // Defenses registerMultiblock(AreaShield5) registerMultiblock(AreaShield10) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 79949b7337..0d19f32cc6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -397,7 +397,7 @@ class MultiblockShape { fun emeraldBlock() = type(Material.EMERALD_BLOCK) fun redstoneBlock() = type(Material.REDSTONE_BLOCK) fun lapisBlock() = type(Material.LAPIS_BLOCK) - fun copperBlock() = anyType( + fun anyCopperVariant() = anyType( Material.COPPER_BLOCK, Material.EXPOSED_COPPER, Material.WEATHERED_COPPER, @@ -414,8 +414,21 @@ class MultiblockShape { Material.WAXED_EXPOSED_CUT_COPPER, Material.WAXED_WEATHERED_CUT_COPPER, Material.WAXED_OXIDIZED_CUT_COPPER, - alias = "any copper block", + alias = "any copper variant", ) + fun anyCopperBlock() = anyType( + Material.COPPER_BLOCK, + Material.EXPOSED_COPPER, + Material.WEATHERED_COPPER, + Material.OXIDIZED_COPPER, + Material.WAXED_COPPER_BLOCK, + Material.WAXED_EXPOSED_COPPER, + Material.WAXED_WEATHERED_COPPER, + Material.WAXED_OXIDIZED_COPPER, + alias = "any solid copper block" + ) + fun copperGrate() = type(Material.COPPER_GRATE) + fun fluidInput() = type(Material.FLETCHING_TABLE) fun titaniumBlock() = customBlock(CustomBlocks.TITANIUM_BLOCK) fun aluminumBlock() = customBlock(CustomBlocks.ALUMINUM_BLOCK) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index b5479f7954..15712bf5bc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -44,9 +44,9 @@ object AmmoLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti z(+2) { y(-1) { x(-2).ironBlock() - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).sponge() - x(+1).copperBlock() + x(+1).anyCopperVariant() x(+2).ironBlock() } @@ -62,9 +62,9 @@ object AmmoLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti z(+3) { y(-1) { x(-2).anyGlassPane() - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).aluminumBlock() - x(+1).copperBlock() + x(+1).anyCopperVariant() x(+2).anyGlassPane() } @@ -80,9 +80,9 @@ object AmmoLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti z(+4) { y(-1) { x(-2).ironBlock() - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).sponge() - x(+1).copperBlock() + x(+1).anyCopperVariant() x(+2).ironBlock() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index 92d45ac892..cfd503f5ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -48,9 +48,9 @@ abstract class AmmoPressMultiblock : Multiblock(), PowerStoringMultiblock, Furna z(+2) { y(-1) { - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).sponge() - x(+1).copperBlock() + x(+1).anyCopperVariant() } y(+0) { @@ -76,9 +76,9 @@ abstract class AmmoPressMultiblock : Multiblock(), PowerStoringMultiblock, Furna z(+4) { y(-1) { - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).sponge() - x(+1).copperBlock() + x(+1).anyCopperVariant() } y(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt index ab91fac2ed..0fd1ed36de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt @@ -75,7 +75,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultibloc "&8Radius: &a$radius" ) - override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, signOffset: BlockFace): AreaShieldEntity { + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AreaShieldEntity { return AreaShieldEntity( manager, this, @@ -83,7 +83,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultibloc y, z, world, - signOffset, + structureDirection, data.getAdditionalDataOrDefault(POWER, INTEGER, 0), maxPower ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt index c043fea938..0a33bf2b72 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt @@ -52,27 +52,27 @@ object GasPowerPlantMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMu x(+2).anyGlassPane() } y(-1) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).extractor() x(+0).wireInputComputer() x(+1).extractor() - x(+2).copperBlock() + x(+2).anyCopperVariant() } } z(+1) { y(+0) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).lightningRod() x(+0).sponge() x(+1).lightningRod() - x(+2).copperBlock() + x(+2).anyCopperVariant() } y(-1) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).anyWall() x(+0).redstoneBlock() x(+1).anyWall() - x(+2).copperBlock() + x(+2).anyCopperVariant() } } z(+2) { @@ -84,11 +84,11 @@ object GasPowerPlantMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMu x(+2).anyGlass() } y(-1) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).anyWall() x(+0).redstoneBlock() x(+1).anyWall() - x(+2).copperBlock() + x(+2).anyCopperVariant() } } z(+3) { @@ -116,27 +116,27 @@ object GasPowerPlantMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMu x(+2).anyGlass() } y(-1) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).anyWall() x(+0).redstoneBlock() x(+1).anyWall() - x(+2).copperBlock() + x(+2).anyCopperVariant() } } z(+5) { y(+0) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).lightningRod() x(+0).sponge() x(+1).lightningRod() - x(+2).copperBlock() + x(+2).anyCopperVariant() } y(-1) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).anyWall() x(+0).redstoneBlock() x(+1).anyWall() - x(+2).copperBlock() + x(+2).anyCopperVariant() } } z(+6) { @@ -148,11 +148,11 @@ object GasPowerPlantMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMu x(+2).anyGlassPane() } y(-1) { - x(-2).copperBlock() + x(-2).anyCopperVariant() x(-1).ironBlock() x(+0).extractor() x(+1).ironBlock() - x(+2).copperBlock() + x(+2).anyCopperVariant() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt new file mode 100644 index 0000000000..fa7be18722 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt @@ -0,0 +1,115 @@ +package net.horizonsend.ion.server.features.multiblock.type.gas + +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.CategoryRestrictedInternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.InternalStorage +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GOLD +import net.kyori.adventure.text.format.NamedTextColor.RED +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent + +object PipedGasCollectorMultiblock : Multiblock(), + EntityMultiblock, + InteractableMultiblock { + override val name: String = "gascollector" + + override val signText: Array = arrayOf( + ofChildren(text("Gas ", RED), text("Collector", GOLD)), + null, + null, + null + ) + + override fun MultiblockShape.buildStructure() { + z(0) { + y(0) { + x(-1).lightningRod() + x(0).anyCopperBlock() + x(+1).lightningRod() + } + y(-1) { + x(-1).anyStairs() + x(0).fluidInput() + x(+1).anyStairs() + } + } + z(+1) { + y(0) { + x(-1).titaniumBlock() + x(0).copperGrate() + x(+1).titaniumBlock() + } + y(-1) { + x(-1).titaniumBlock() + x(0).copperGrate() + x(+1).titaniumBlock() + } + + } + z(+2) { + y(0) { + x(-1).lightningRod() + x(0).anyCopperBlock() + x(+1).lightningRod() + } + y(-1) { + x(-1).anyStairs() + x(0).anyCopperBlock() + x(+1).anyStairs() + } + + } + } + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val entity = getMultiblockEntity(sign) + + player.information("Entity: $entity") + } + + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): GasCollectorEntity { + return GasCollectorEntity(manager, x, y, z, world, structureDirection) + } + + class GasCollectorEntity( + manager: ChunkMultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, PipedGasCollectorMultiblock, x, y, z, world, structureDirection), + AsyncTickingMultiblockEntity, + FluidStoringEntity + { + override val capacities: Array = arrayOf(CategoryRestrictedInternalStorage(500, FluidCategory.GAS)) + + override suspend fun tickAsync() { + firstCasStore(TransportedFluids.HYDROGEN, 1.0)?.addAmount(1) + } + + override fun toString(): String { + return """ + Piped gas collector :) + Storage: ${getStoredResources()} + """.trimIndent() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index 973de293e7..34070bffd5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -32,9 +32,9 @@ object CentrifugeMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti z(+1) { y(-1) { x(-2).anyGlassPane() - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).endRod() - x(+1).copperBlock() + x(+1).anyCopperVariant() x(+2).anyGlassPane() } y(+0) { @@ -48,9 +48,9 @@ object CentrifugeMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti z(+2) { y(-1) { x(-2).ironBlock() - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).sponge() - x(+1).copperBlock() + x(+1).anyCopperVariant() x(+2).ironBlock() } y(+0) { @@ -64,9 +64,9 @@ object CentrifugeMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti z(+3) { y(-1) { x(-2).anyGlassPane() - x(-1).copperBlock() + x(-1).anyCopperVariant() x(+0).endRod() - x(+1).copperBlock() + x(+1).anyCopperVariant() x(+2).anyGlassPane() } y(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 49b08498c2..8b94f679dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -83,8 +83,8 @@ object MobDefender : Multiblock(), EntityMultiblock { * Create the multiblock entity using the stored data **/ fun createEntity( - manager: ChunkMultiblockManager, - data: PersistentMultiblockData, - world: World, - x: Int, - y: Int, - z: Int, - signOffset: BlockFace + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + structureDirection: BlockFace ): T fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): T? { @@ -33,4 +35,11 @@ interface EntityMultiblock { @Suppress("UNCHECKED_CAST") return world.ion.getChunk(chunkX, chunkZ)?.multiblockManager?.get(x, y, z) as T? } + + fun getMultiblockEntity(sign: Sign): T? { + val origin = MultiblockEntity.getOriginFromSign(sign) + + @Suppress("UNCHECKED_CAST") + return MultiblockEntities.getMultiblockEntity(origin) as T? + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt index 061ec5261c..2d2520fb7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt @@ -17,59 +17,59 @@ object CapitalBeamStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt index 7e31bad92f..2cd78c2f31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt @@ -2,28 +2,26 @@ package net.horizonsend.ion.server.features.transport.fluids import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.gas.Gasses -import net.horizonsend.ion.server.features.transport.fluids.types.BasicFluid -import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid // object TransportedFluids : IonServerComponent() { - val HYDROGEN = register(GasFluid { Gasses.HYDROGEN }) - val NITROGEN = register(GasFluid { Gasses.NITROGEN }) - val METHANE = register(GasFluid { Gasses.METHANE }) - val OXYGEN = register(GasFluid { Gasses.OXYGEN }) - val CHLORINE = register(GasFluid { Gasses.CHLORINE }) - val FLUORINE = register(GasFluid { Gasses.FLUORINE }) - val HELIUM = register(GasFluid { Gasses.FLUORINE }) - val CARBON_DIOXIDE = register(GasFluid { Gasses.FLUORINE }) + private val pipedFluids = mutableListOf() - private val fluids = mutableListOf() + val HYDROGEN = register(GasPipedFluid { Gasses.HYDROGEN }) + val NITROGEN = register(GasPipedFluid { Gasses.NITROGEN }) + val METHANE = register(GasPipedFluid { Gasses.METHANE }) + val OXYGEN = register(GasPipedFluid { Gasses.OXYGEN }) + val CHLORINE = register(GasPipedFluid { Gasses.CHLORINE }) + val FLUORINE = register(GasPipedFluid { Gasses.FLUORINE }) + val HELIUM = register(GasPipedFluid { Gasses.FLUORINE }) + val CARBON_DIOXIDE = register(GasPipedFluid { Gasses.FLUORINE }) - fun register(fluid: T): T { - fluids.add(fluid) - return fluid - } + fun register(fluid: T): T { + pipedFluids.add(fluid) - fun registerBasic(): BasicFluid { - throw NotImplementedError() + fluid.categories.forEach { it.addMember(fluid) } + + return fluid } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt new file mode 100644 index 0000000000..e7c5451a90 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.transport.fluids.properties + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +enum class FluidCategory { + GAS; + + private val members = mutableListOf() + + fun getMembers(): List = members + + fun addMember(fluid: PipedFluid) = members.add(fluid) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt deleted file mode 100644 index 45e2ebe217..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicFluid.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.horizonsend.ion.server.features.transport.fluids.types - -import net.horizonsend.ion.server.features.transport.fluids.Fluid - -class BasicFluid : Fluid() { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt new file mode 100644 index 0000000000..2309c13abb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.fluids.types + +class BasicPipedFluid /*: PipedFluid()*/ { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt deleted file mode 100644 index 3e323591b2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.horizonsend.ion.server.features.transport.fluids.types - -import net.horizonsend.ion.server.features.gas.type.Gas -import net.horizonsend.ion.server.features.transport.fluids.Fluid -import java.util.function.Supplier - -class GasFluid( - private val gasSupplier: Supplier -) : Fluid() { - val gas get() = gasSupplier.get() -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt new file mode 100644 index 0000000000..b67ce175ea --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.transport.fluids.types + +import net.horizonsend.ion.server.features.gas.type.Gas +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import java.util.function.Supplier + +class GasPipedFluid( + private val gasSupplier: Supplier +) : PipedFluid() { + override val categories: Array = arrayOf(FluidCategory.GAS) + + val gas get() = gasSupplier.get() +} From ef24769b5463afee467d43df542bc8cd84a80288 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 14:18:09 -0500 Subject: [PATCH 115/500] Storage improvements --- .../server/command/admin/IonChunkCommand.kt | 6 ++- .../display/container/DisplayHandlers.kt | 1 - .../entity/PersistentMultiblockData.kt | 2 + .../CategoryRestrictedInternalStorage.kt | 16 +++++- .../entity/type/fluids/ContainerType.kt | 50 +++++++++++++++++++ .../entity/type/fluids/FluidStoringEntity.kt | 49 ++++++++++++++++-- .../entity/type/fluids/InternalStorage.kt | 46 ++++++++++++++++- .../entity/type/fluids/SingleFluidStorage.kt | 6 +++ .../entity/type/fluids/StorageContainer.kt | 16 ++++++ .../type/fluids/UnlimitedInternalStorage.kt | 2 + .../type/gas/PipedGasCollectorMultiblock.kt | 31 ++++++++++-- .../world/ChunkMultiblockManager.kt | 4 +- .../features/transport/fluids/PipedFluid.kt | 6 ++- .../transport/fluids/TransportedFluids.kt | 26 +++++++--- .../fluids/properties/FluidCategory.kt | 7 +++ .../transport/fluids/types/GasPipedFluid.kt | 5 +- .../persistence/NamespacedKeys.kt | 5 ++ .../server/miscellaneous/utils/Collections.kt | 2 + 18 files changed, 253 insertions(+), 27 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 419f1cc8db..88f97d5f31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -26,7 +26,8 @@ import org.bukkit.entity.Player object IonChunkCommand : SLCommand() { @Subcommand("dumpEntities") fun onDumpEntities(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { - val entities = sender.chunk.ion().multiblockManager.getAllMultiblockEntities().toList() + val manager = sender.chunk.ion().multiblockManager + val entities = manager.getAllMultiblockEntities().toList() sender.sendMessage(formatPaginatedMenu( entities.size, @@ -47,6 +48,9 @@ object IonChunkCommand : SLCommand() { sender.highlightBlock(vec, 30L) } } + + sender.information("Sync Ticked: ${manager.syncTickingMultiblockEntities}") + sender.information("Async Ticked: ${manager.asyncTickingMultiblockEntities}") } @Subcommand("remove all") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt index 29c5d68831..f1d6d655ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt @@ -18,7 +18,6 @@ object DisplayHandlers : IonServerComponent() { toRemove } - println("Have ${displayHolders.size} handlers") for (displayHolder in displayHolders) { displayHolder.refresh() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index 71b2c60a1c..04e6209abd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -31,6 +31,8 @@ class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Mul fun getAdditionalData(key: NamespacedKey, type: PersistentDataType<*, Z>) = additionalData.get(key, type) fun getAdditionalDataOrDefault(key: NamespacedKey, type: PersistentDataType<*, Z>, default: Z) = additionalData.getOrDefault(key, type, default) + fun getAdditionalDataRaw(): PersistentDataContainer = additionalData + companion object : PersistentDataType { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = PersistentMultiblockData::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt index d4123d09f2..702710efdd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt @@ -2,19 +2,31 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_CATEGORIES +import org.bukkit.persistence.PersistentDataContainer class CategoryRestrictedInternalStorage( private val storageCapacity: Int, private vararg val allowedCategories: FluidCategory ) : InternalStorage() { + override val containerType: ContainerType = ContainerType.CATEGORY_RESTRICTED_INTERNAL_STORAGE + override fun getCapacity(): Int = storageCapacity override fun canStore(resource: PipedFluid, liters: Double): Boolean { - if (liters + getAmount() > getCapacity()) return false + if (liters + getAmount() > getCapacity()) { + return false + } // Check that the fluid attempting to be stored is the same as the one currently stored - if (getStoredFluid() != null && resource != getStoredFluid()) return false + if (getStoredFluid() != null && resource != getStoredFluid()) { + return false + } return allowedCategories.intersect(resource.categories.toSet()).isNotEmpty() } + + override fun saveAdditionalData(pdc: PersistentDataContainer) { + pdc.set(FLUID_CATEGORIES, FluidCategory.listDataType, allowedCategories.toList()) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt new file mode 100644 index 0000000000..d77ea10d35 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt @@ -0,0 +1,50 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_CATEGORIES +import net.horizonsend.ion.server.miscellaneous.utils.orEmpty +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +enum class ContainerType { + UNLIMITED_INTERNAL_STORAGE { + override fun create(primitive: PersistentDataContainer): InternalStorage { + val capacity = primitive.get(NamespacedKeys.RESOURCE_CAPACITY_MAX, PersistentDataType.INTEGER)!! + + val storage = UnlimitedInternalStorage(capacity) + + val fluid = primitive.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } + val amount = primitive.getOrDefault(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, 0) + + storage.setFluid(fluid) + storage.setAmount(amount) + + return storage + } + }, + CATEGORY_RESTRICTED_INTERNAL_STORAGE { + override fun create(primitive: PersistentDataContainer): InternalStorage { + val capacity = primitive.get(NamespacedKeys.RESOURCE_CAPACITY_MAX, PersistentDataType.INTEGER)!! + val categories = primitive.get(FLUID_CATEGORIES, FluidCategory.listDataType).orEmpty().toTypedArray() + + val storage = CategoryRestrictedInternalStorage(capacity, *categories) + + val fluid = primitive.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } + val amount = primitive.getOrDefault(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, 0) + + storage.setFluid(fluid) + storage.setAmount(amount) + + return storage + } + }; + + abstract fun create(primitive: PersistentDataContainer): InternalStorage + + companion object { + val persistentDataType = EnumDataType(ContainerType::class.java) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 3bbd0ff2a7..8956b2604d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -1,13 +1,54 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES +import net.kyori.adventure.text.Component +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { - val capacities: Array + val capacities: Array - fun canStore(fluid: PipedFluid, amount: Double) = capacities.any { it.canStore(fluid, amount) } + fun canStore(fluid: PipedFluid, amount: Double) = capacities.any { it.storage.canStore(fluid, amount) } - fun firstCasStore(fluid: PipedFluid, amount: Double): InternalStorage? = capacities.firstOrNull { it.canStore(fluid, amount) } + fun firstCasStore(fluid: PipedFluid, amount: Double): StorageContainer? = capacities.firstOrNull { it.storage.canStore(fluid, amount) } - fun getStoredResources() : Map = capacities.associate { it.getStoredFluid() to it.getAmount().toDouble() } + fun getStoredResources() : Map = capacities.associate { it.storage.getStoredFluid() to it.storage.getAmount().toDouble() } + + fun storeStorageData(destination: PersistentDataContainer, context: PersistentDataAdapterContext) { + val storages = context.newPersistentDataContainer() + + capacities.forEach { + it.save(storages) + } + + destination.set(STORAGES, TAG_CONTAINER, storages) + } + + /** + * Loads the defined resource storage container from the configuration, or constructs a new one with the information provided. + **/ + fun loadStoredResource( + data: PersistentMultiblockData, + name: String, + displayName: Component, + namespacedKey: NamespacedKey, + storageDefault: () -> InternalStorage + ): StorageContainer { + val storages = data.getAdditionalData(STORAGES, TAG_CONTAINER) + + val internalStorage = storages?.let { containers -> + containers.get(namespacedKey, InternalStorage)!! + } + + return StorageContainer( + name, + displayName, + namespacedKey, + internalStorage ?: storageDefault.invoke() + ) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt index 6977a48e88..897283a099 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt @@ -1,13 +1,19 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType /** * Fluid storing multiblocks can have a single, or multiple fluid storage capacities * * Each internal storage can hold a single type of fluid **/ -abstract class InternalStorage { +abstract class InternalStorage : PDCSerializable { + abstract val containerType: ContainerType protected var amountUnsafe: Int = 0 protected var fluidUnsafe: PipedFluid? = null @@ -21,6 +27,14 @@ abstract class InternalStorage { setAmount(getAmount() + amount) } + fun addAmount(fluid: PipedFluid, amount: Int) { + if (getStoredFluid() != null && fluid != getStoredFluid()) return + + if (getStoredFluid() == null) setFluid(fluid) + + addAmount(amount) + } + fun getAmount(): Int = amountUnsafe fun setContents(fluid: PipedFluid, amount: Int) { @@ -47,4 +61,34 @@ abstract class InternalStorage { open fun updateVisually() {} fun getContents(): Pair = fluidUnsafe to getAmount() + + override val persistentDataType: Companion = Companion + + open fun saveAdditionalData(pdc: PersistentDataContainer) {} + + companion object : PersistentDataType { + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + override fun getComplexType(): Class = InternalStorage::class.java + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): InternalStorage { + val type = primitive.get(NamespacedKeys.CONTAINER_TYPE, ContainerType.persistentDataType)!! + return type.create(primitive) + } + + override fun toPrimitive(complex: InternalStorage, context: PersistentDataAdapterContext): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + pdc.set(NamespacedKeys.CONTAINER_TYPE, ContainerType.persistentDataType, complex.containerType) + pdc.set(NamespacedKeys.RESOURCE_CAPACITY_MAX, PersistentDataType.INTEGER, complex.getCapacity()) + + val fluid = complex.getStoredFluid() + if (fluid != null) { + pdc.set(NamespacedKeys.FLUID, PersistentDataType.STRING, fluid.identifier) + pdc.set(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, complex.getAmount()) + } + + complex.saveAdditionalData(pdc) + + return pdc + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt new file mode 100644 index 0000000000..80fc235662 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import org.bukkit.Fluid + +class SingleFluidStorage(private val fluid: Fluid, private val storageCapacity: Int) { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt new file mode 100644 index 0000000000..d1ea490524 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt @@ -0,0 +1,16 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import net.kyori.adventure.text.Component +import org.bukkit.NamespacedKey +import org.bukkit.persistence.PersistentDataContainer + +class StorageContainer( + val name: String, + val displayName: Component, + private val namespacedKey: NamespacedKey, + val storage: InternalStorage +) { + fun save(destination: PersistentDataContainer) { + destination.set(namespacedKey, InternalStorage, storage) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt index 5a092735c5..1f3eb82f7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt @@ -6,6 +6,8 @@ import net.horizonsend.ion.server.features.transport.fluids.PipedFluid * Internal storage with no limits on what fluid can be stored **/ class UnlimitedInternalStorage(private val storageCapacity: Int) : InternalStorage() { + override val containerType: ContainerType = ContainerType.UNLIMITED_INTERNAL_STORAGE + override fun getCapacity(): Int = storageCapacity override fun canStore(resource: PipedFluid, liters: Double): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt index fa7be18722..57d6988969 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt @@ -8,13 +8,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.CategoryRestrictedInternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.InternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.StorageContainer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GOLD @@ -85,11 +86,12 @@ object PipedGasCollectorMultiblock : Multiblock(), } override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): GasCollectorEntity { - return GasCollectorEntity(manager, x, y, z, world, structureDirection) + return GasCollectorEntity(manager, data, x, y, z, world, structureDirection) } class GasCollectorEntity( manager: ChunkMultiblockManager, + data: PersistentMultiblockData, x: Int, y: Int, z: Int, @@ -99,10 +101,29 @@ object PipedGasCollectorMultiblock : Multiblock(), AsyncTickingMultiblockEntity, FluidStoringEntity { - override val capacities: Array = arrayOf(CategoryRestrictedInternalStorage(500, FluidCategory.GAS)) + override val capacities: Array = arrayOf( + loadStoredResource(data, "main", text("Main Gas Storage"), NamespacedKeys.GAS) { CategoryRestrictedInternalStorage(500, FluidCategory.GAS) }, + ) override suspend fun tickAsync() { - firstCasStore(TransportedFluids.HYDROGEN, 1.0)?.addAmount(1) + firstCasStore(HYDROGEN, 1.0)?.storage?.addAmount(HYDROGEN, 1) + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + val rawStorage = store.getAdditionalDataRaw() + storeStorageData(rawStorage, rawStorage.adapterContext) + } + + override fun onLoad() { + + } + + override fun onUnload() { + + } + + override fun handleRemoval() { + } override fun toString(): String { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt index 4ec7e314c0..9353ba7952 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt @@ -30,8 +30,8 @@ class ChunkMultiblockManager(val chunk: IonChunk) { private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** All the ticked multiblock entities of this chunk */ - private val syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() - private val asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + val syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + val asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** * Logic upon the chunk being ticked diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt index 647492afdf..f5183ccc00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt @@ -2,6 +2,10 @@ package net.horizonsend.ion.server.features.transport.fluids import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory -abstract class PipedFluid { +abstract class PipedFluid(val identifier: String) { abstract val categories: Array + + override fun toString(): String { + return "FLUID[$identifier]" + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt index 2cd78c2f31..74844883fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt @@ -3,19 +3,25 @@ package net.horizonsend.ion.server.features.transport.fluids import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid +import java.util.concurrent.ConcurrentHashMap // object TransportedFluids : IonServerComponent() { private val pipedFluids = mutableListOf() + private val byIdentifier = ConcurrentHashMap() - val HYDROGEN = register(GasPipedFluid { Gasses.HYDROGEN }) - val NITROGEN = register(GasPipedFluid { Gasses.NITROGEN }) - val METHANE = register(GasPipedFluid { Gasses.METHANE }) - val OXYGEN = register(GasPipedFluid { Gasses.OXYGEN }) - val CHLORINE = register(GasPipedFluid { Gasses.CHLORINE }) - val FLUORINE = register(GasPipedFluid { Gasses.FLUORINE }) - val HELIUM = register(GasPipedFluid { Gasses.FLUORINE }) - val CARBON_DIOXIDE = register(GasPipedFluid { Gasses.FLUORINE }) + val HYDROGEN = register(GasPipedFluid("HYDROGEN") { Gasses.HYDROGEN }) + val NITROGEN = register(GasPipedFluid("NITROGEN") { Gasses.NITROGEN }) + val METHANE = register(GasPipedFluid("METHANE") { Gasses.METHANE }) + val OXYGEN = register(GasPipedFluid("OXYGEN") { Gasses.OXYGEN }) + val CHLORINE = register(GasPipedFluid("CHLORINE") { Gasses.CHLORINE }) + val FLUORINE = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) + val HELIUM = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) + val CARBON_DIOXIDE = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) + + init { + pipedFluids.associateByTo(byIdentifier) { it.identifier } + } fun register(fluid: T): T { pipedFluids.add(fluid) @@ -24,4 +30,8 @@ object TransportedFluids : IonServerComponent() { return fluid } + + operator fun get(identifier: String): PipedFluid? { + return byIdentifier[identifier] + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt index e7c5451a90..f9b06c99bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.transport.fluids.properties +import com.manya.pdc.DataTypes +import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.fluids.PipedFluid enum class FluidCategory { @@ -10,4 +12,9 @@ enum class FluidCategory { fun getMembers(): List = members fun addMember(fluid: PipedFluid) = members.add(fluid) + + companion object { + val persistentDataType = EnumDataType(FluidCategory::class.java) + val listDataType = DataTypes.list(persistentDataType) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt index b67ce175ea..9afdf235fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt @@ -6,8 +6,9 @@ import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCate import java.util.function.Supplier class GasPipedFluid( - private val gasSupplier: Supplier -) : PipedFluid() { + identifier: String, + private val gasSupplier: Supplier, +) : PipedFluid(identifier) { override val categories: Array = arrayOf(FluidCategory.GAS) val gas get() = gasSupplier.get() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 1772c40167..1710ea9da5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -104,7 +104,12 @@ object NamespacedKeys { val NODES = key("chunk_nodes") + // Fluid storage + val CONTAINER_TYPE = key("container_type") + val FLUID = key("fluid") + val STORAGES = key("storages") + val FLUID_CATEGORIES = key("fluid_categories") fun key(key: String) = NamespacedKey(IonServer, key) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index b596ad2022..b32d47653d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -138,3 +138,5 @@ inline fun Collection.averageBy(transform: (T) -> Double): Double { return total / size } + +fun MutableList?.orEmpty(): MutableList = this ?: mutableListOf() From d19eb1d4528e0684ad2dc3c25d06813622f598c3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 14:31:37 -0500 Subject: [PATCH 116/500] Don't store unnecessary info --- .../CategoryRestrictedInternalStorage.kt | 8 --- .../entity/type/fluids/ContainerType.kt | 50 ------------------- .../entity/type/fluids/FluidStoringEntity.kt | 8 +-- .../entity/type/fluids/InternalStorage.kt | 40 +++++---------- .../entity/type/fluids/StorageContainer.kt | 6 ++- .../type/fluids/UnlimitedInternalStorage.kt | 2 - .../type/gas/PipedGasCollectorMultiblock.kt | 2 +- .../persistence/NamespacedKeys.kt | 2 +- 8 files changed, 24 insertions(+), 94 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt index 702710efdd..fa18d6019c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt @@ -2,15 +2,11 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_CATEGORIES -import org.bukkit.persistence.PersistentDataContainer class CategoryRestrictedInternalStorage( private val storageCapacity: Int, private vararg val allowedCategories: FluidCategory ) : InternalStorage() { - override val containerType: ContainerType = ContainerType.CATEGORY_RESTRICTED_INTERNAL_STORAGE - override fun getCapacity(): Int = storageCapacity override fun canStore(resource: PipedFluid, liters: Double): Boolean { @@ -25,8 +21,4 @@ class CategoryRestrictedInternalStorage( return allowedCategories.intersect(resource.categories.toSet()).isNotEmpty() } - - override fun saveAdditionalData(pdc: PersistentDataContainer) { - pdc.set(FLUID_CATEGORIES, FluidCategory.listDataType, allowedCategories.toList()) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt deleted file mode 100644 index d77ea10d35..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/ContainerType.kt +++ /dev/null @@ -1,50 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.fluids - -import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids -import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_CATEGORIES -import net.horizonsend.ion.server.miscellaneous.utils.orEmpty -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -enum class ContainerType { - UNLIMITED_INTERNAL_STORAGE { - override fun create(primitive: PersistentDataContainer): InternalStorage { - val capacity = primitive.get(NamespacedKeys.RESOURCE_CAPACITY_MAX, PersistentDataType.INTEGER)!! - - val storage = UnlimitedInternalStorage(capacity) - - val fluid = primitive.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } - val amount = primitive.getOrDefault(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, 0) - - storage.setFluid(fluid) - storage.setAmount(amount) - - return storage - } - }, - CATEGORY_RESTRICTED_INTERNAL_STORAGE { - override fun create(primitive: PersistentDataContainer): InternalStorage { - val capacity = primitive.get(NamespacedKeys.RESOURCE_CAPACITY_MAX, PersistentDataType.INTEGER)!! - val categories = primitive.get(FLUID_CATEGORIES, FluidCategory.listDataType).orEmpty().toTypedArray() - - val storage = CategoryRestrictedInternalStorage(capacity, *categories) - - val fluid = primitive.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } - val amount = primitive.getOrDefault(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, 0) - - storage.setFluid(fluid) - storage.setAmount(amount) - - return storage - } - }; - - abstract fun create(primitive: PersistentDataContainer): InternalStorage - - companion object { - val persistentDataType = EnumDataType(ContainerType::class.java) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 8956b2604d..9dfa06bf93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -36,19 +36,19 @@ interface FluidStoringEntity { name: String, displayName: Component, namespacedKey: NamespacedKey, - storageDefault: () -> InternalStorage + internalStorage: InternalStorage ): StorageContainer { val storages = data.getAdditionalData(STORAGES, TAG_CONTAINER) - val internalStorage = storages?.let { containers -> - containers.get(namespacedKey, InternalStorage)!! + storages?.get(namespacedKey, TAG_CONTAINER)?.let { + internalStorage.loadData(it) } return StorageContainer( name, displayName, namespacedKey, - internalStorage ?: storageDefault.invoke() + internalStorage ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt index 897283a099..396ea01ab2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt @@ -1,9 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable -import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -12,8 +11,7 @@ import org.bukkit.persistence.PersistentDataType * * Each internal storage can hold a single type of fluid **/ -abstract class InternalStorage : PDCSerializable { - abstract val containerType: ContainerType +abstract class InternalStorage { protected var amountUnsafe: Int = 0 protected var fluidUnsafe: PipedFluid? = null @@ -62,33 +60,21 @@ abstract class InternalStorage : PDCSerializable = fluidUnsafe to getAmount() - override val persistentDataType: Companion = Companion - open fun saveAdditionalData(pdc: PersistentDataContainer) {} - companion object : PersistentDataType { - override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - override fun getComplexType(): Class = InternalStorage::class.java - - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): InternalStorage { - val type = primitive.get(NamespacedKeys.CONTAINER_TYPE, ContainerType.persistentDataType)!! - return type.create(primitive) - } - - override fun toPrimitive(complex: InternalStorage, context: PersistentDataAdapterContext): PersistentDataContainer { - val pdc = context.newPersistentDataContainer() - pdc.set(NamespacedKeys.CONTAINER_TYPE, ContainerType.persistentDataType, complex.containerType) - pdc.set(NamespacedKeys.RESOURCE_CAPACITY_MAX, PersistentDataType.INTEGER, complex.getCapacity()) + fun loadData(pdc: PersistentDataContainer) { + val fluid = pdc.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } + val amount = pdc.getOrDefault(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, 0) - val fluid = complex.getStoredFluid() - if (fluid != null) { - pdc.set(NamespacedKeys.FLUID, PersistentDataType.STRING, fluid.identifier) - pdc.set(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, complex.getAmount()) - } + setFluid(fluid) + setAmount(amount) + } - complex.saveAdditionalData(pdc) + fun saveData(destination: PersistentDataContainer) { + val fluid = getStoredFluid() ?: return + val amount = getAmount() - return pdc - } + destination.set(NamespacedKeys.FLUID, PersistentDataType.STRING, fluid.identifier) + destination.set(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, amount) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt index d1ea490524..936c228a1b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.kyori.adventure.text.Component import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER class StorageContainer( val name: String, @@ -11,6 +12,9 @@ class StorageContainer( val storage: InternalStorage ) { fun save(destination: PersistentDataContainer) { - destination.set(namespacedKey, InternalStorage, storage) + val pdc = destination.adapterContext.newPersistentDataContainer() + storage.saveData(pdc) + + destination.set(namespacedKey, TAG_CONTAINER, pdc) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt index 1f3eb82f7a..5a092735c5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt @@ -6,8 +6,6 @@ import net.horizonsend.ion.server.features.transport.fluids.PipedFluid * Internal storage with no limits on what fluid can be stored **/ class UnlimitedInternalStorage(private val storageCapacity: Int) : InternalStorage() { - override val containerType: ContainerType = ContainerType.UNLIMITED_INTERNAL_STORAGE - override fun getCapacity(): Int = storageCapacity override fun canStore(resource: PipedFluid, liters: Double): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt index 57d6988969..dfc207bde5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt @@ -102,7 +102,7 @@ object PipedGasCollectorMultiblock : Multiblock(), FluidStoringEntity { override val capacities: Array = arrayOf( - loadStoredResource(data, "main", text("Main Gas Storage"), NamespacedKeys.GAS) { CategoryRestrictedInternalStorage(500, FluidCategory.GAS) }, + loadStoredResource(data, "main", text("Main Gas Storage"), NamespacedKeys.GAS, CategoryRestrictedInternalStorage(500, FluidCategory.GAS)) ) override suspend fun tickAsync() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 1710ea9da5..5837c727a7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -105,8 +105,8 @@ object NamespacedKeys { val NODES = key("chunk_nodes") // Fluid storage - val CONTAINER_TYPE = key("container_type") val FLUID = key("fluid") + val CONTAINER_TYPE = key("container_type") val STORAGES = key("storages") val FLUID_CATEGORIES = key("fluid_categories") From 4024f95f3aa521c038d0009ac2d0f3fdb73b33c1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 14:38:15 -0500 Subject: [PATCH 117/500] organize power multiblocks --- .../server/features/multiblock/Multiblocks.kt | 24 +++++++++---------- .../newer/MultiblockRegistration.kt | 10 ++++---- .../{gas => fluid}/GasPowerPlantMultiblock.kt | 2 +- .../type/{gas => fluid}/VentMultiblock.kt | 2 +- .../collector}/GasCollectorMultiblock.kt | 2 +- .../collector}/PipedGasCollectorMultiblock.kt | 2 +- .../{ => power}/charger/ChargerMultiblock.kt | 2 +- .../charger/ChargerMultiblockTier1.kt | 2 +- .../charger/ChargerMultiblockTier2.kt | 2 +- .../charger/ChargerMultiblockTier3.kt | 2 +- .../generator/GeneratorMultiblock.kt | 2 +- .../generator/GeneratorMultiblockTier1.kt | 2 +- .../generator/GeneratorMultiblockTier2.kt | 2 +- .../generator/GeneratorMultiblockTier3.kt | 2 +- .../powerfurnace/PowerFurnaceMultiblock.kt | 2 +- .../PowerFurnaceMultiblockTier1.kt | 2 +- .../PowerFurnaceMultiblockTier2.kt | 2 +- .../PowerFurnaceMultiblockTier3.kt | 2 +- .../storage}/PowerBankMultiblock.kt | 2 +- .../storage}/PowerBankMultiblockTier1.kt | 2 +- .../storage}/PowerBankMultiblockTier2.kt | 2 +- .../storage}/PowerBankMultiblockTier3.kt | 2 +- .../storage}/PowerCellMultiblock.kt | 2 +- 23 files changed, 38 insertions(+), 38 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{gas => fluid}/GasPowerPlantMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{gas => fluid}/VentMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{gas => fluid/collector}/GasCollectorMultiblock.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{gas => fluid/collector}/PipedGasCollectorMultiblock.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/charger/ChargerMultiblock.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/charger/ChargerMultiblockTier1.kt (78%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/charger/ChargerMultiblockTier2.kt (75%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/charger/ChargerMultiblockTier3.kt (78%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/generator/GeneratorMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/generator/GeneratorMultiblockTier1.kt (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/generator/GeneratorMultiblockTier2.kt (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/generator/GeneratorMultiblockTier3.kt (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/powerfurnace/PowerFurnaceMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/powerfurnace/PowerFurnaceMultiblockTier1.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/powerfurnace/PowerFurnaceMultiblockTier2.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => power}/powerfurnace/PowerFurnaceMultiblockTier3.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{powerbank => power/storage}/PowerBankMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{powerbank => power/storage}/PowerBankMultiblockTier1.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{powerbank => power/storage}/PowerBankMultiblockTier2.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{powerbank => power/storage}/PowerBankMultiblockTier3.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{powerbank => power/storage}/PowerCellMultiblock.kt (99%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index 21b9926bfc..dfce587e93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -16,9 +16,9 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPres import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.charger.ChargerMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 @@ -29,12 +29,12 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.Har import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.gas.GasCollectorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.gas.GasPowerPlantMultiblock -import net.horizonsend.ion.server.features.multiblock.type.gas.VentMultiblock -import net.horizonsend.ion.server.features.multiblock.type.generator.GeneratorMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.generator.GeneratorMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.generator.GeneratorMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.gravitywell.AmplifiedGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.gravitywell.StandardGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock @@ -63,9 +63,9 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirloc import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock -import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.powerfurnace.PowerFurnaceMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 628bdc821d..687c05bfbe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruis import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock -import net.horizonsend.ion.server.features.multiblock.type.gas.PipedGasCollectorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass1 import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass2 import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass3 @@ -41,10 +41,10 @@ import net.horizonsend.ion.server.features.multiblock.type.particleshield.Shield import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass30 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass65 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass85 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerBankMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.powerbank.PowerCellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerCellMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt index 0a33bf2b72..fa9f96c37c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasPowerPlantMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gas +package net.horizonsend.ion.server.features.multiblock.type.fluid import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt index 738e8dad61..aaee0d0a6d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/VentMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gas +package net.horizonsend.ion.server.features.multiblock.type.fluid import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.GasCanister diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt index 959fa3212c..e87f602d9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/GasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gas +package net.horizonsend.ion.server.features.multiblock.type.fluid.collector import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.configuration.ConfigurationFiles diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index dfc207bde5..e6f4197b3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gas/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gas +package net.horizonsend.ion.server.features.multiblock.type.fluid.collector import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.ofChildren diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 8970d670d3..7f18dbe951 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.charger +package net.horizonsend.ion.server.features.multiblock.type.power.charger import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier1.kt similarity index 78% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier1.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier1.kt index 3c4dc9d295..f52a4f0e27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier1.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.charger +package net.horizonsend.ion.server.features.multiblock.type.power.charger import org.bukkit.ChatColor import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier2.kt similarity index 75% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier2.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier2.kt index 5668abd86e..94dd837868 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier2.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.charger +package net.horizonsend.ion.server.features.multiblock.type.power.charger import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier3.kt similarity index 78% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier3.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier3.kt index ddcc212975..ff9818ee75 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/charger/ChargerMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblockTier3.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.charger +package net.horizonsend.ion.server.features.multiblock.type.power.charger import org.bukkit.ChatColor import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 3ff609bfe0..290f346154 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.generator +package net.horizonsend.ion.server.features.multiblock.type.power.generator import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.machine.PowerMachines diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier1.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier1.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier1.kt index 111e64a943..babf871102 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier1.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.generator +package net.horizonsend.ion.server.features.multiblock.type.power.generator import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier2.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier2.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier2.kt index 1c3c5e40f5..73f8361e1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier2.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.generator +package net.horizonsend.ion.server.features.multiblock.type.power.generator import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier3.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier3.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier3.kt index c7c1930697..e0d64e2787 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/generator/GeneratorMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblockTier3.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.generator +package net.horizonsend.ion.server.features.multiblock.type.power.generator import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index e016a1ea69..82bc9b4d5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerfurnace +package net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier1.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier1.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier1.kt index 78d1081f17..794d649cc9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier1.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerfurnace +package net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier2.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier2.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier2.kt index 959abcc14b..b61e4d7cb0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier2.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerfurnace +package net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier3.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier3.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier3.kt index 4f6d9ed58f..312cfb5536 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerfurnace/PowerFurnaceMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblockTier3.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerfurnace +package net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index a2331bfc12..fdc7bf4c0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank +package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier1.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier1.kt index 2440d72d00..7726e6ada9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier1.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank +package net.horizonsend.ion.server.features.multiblock.type.power.storage import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier2.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier2.kt index f832a25815..92c338d9fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier2.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank +package net.horizonsend.ion.server.features.multiblock.type.power.storage import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier3.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier3.kt index c7fa9d9fb6..6fde2a63c1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerBankMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblockTier3.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank +package net.horizonsend.ion.server.features.multiblock.type.power.storage import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 112745a19d..fbdb8aad09 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/powerbank/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.powerbank +package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData From 5e76854dea805a6e2077228bb4cf4e1ed338ef55 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 15:08:24 -0500 Subject: [PATCH 118/500] Add fluid storage multiblocks --- .../newer/MultiblockRegistration.kt | 16 +++- .../multiblock/shape/MultiblockShape.kt | 1 + .../collector/PipedGasCollectorMultiblock.kt | 2 +- .../fluid/storage/FluidStorageMultiblock.kt | 53 +++++++++++++ .../type/fluid/storage/FluidTankLarge.kt | 4 + .../type/fluid/storage/FluidTankMedium.kt | 77 +++++++++++++++++++ .../type/fluid/storage/FluidTankSmall.kt | 44 +++++++++++ .../persistence/NamespacedKeys.kt | 3 +- 8 files changed, 193 insertions(+), 7 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankLarge.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankSmall.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 687c05bfbe..babb10267e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -16,6 +16,8 @@ import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReac import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium +import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass1 import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass2 import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass3 @@ -109,6 +111,9 @@ object MultiblockRegistration : IonServerComponent() { // Gas registerMultiblock(PipedGasCollectorMultiblock) + registerMultiblock(FluidTankSmall) + registerMultiblock(FluidTankMedium) +// registerMultiblock(FluidTankLarge) // Defenses registerMultiblock(AreaShield5) @@ -218,12 +223,15 @@ object MultiblockRegistration : IonServerComponent() { multiblocks[name] = multiblock } - private fun registerMultiblock(multiblock: Multiblock, alias: String) { - if (multiblocks.containsKey(alias)) { - throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[alias]}, new: $multiblock") + /** + * Registers a multiblock under a different storage identifier. This is to be used in the case a class has to be renamed, or similar. + **/ + private fun registerMultiblock(multiblock: Multiblock, storageAlias: String) { + if (multiblocks.containsKey(storageAlias)) { + throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[storageAlias]}, new: $multiblock") } - multiblocks[alias] = multiblock + multiblocks[storageAlias] = multiblock } fun getAllMultiblocks() = multiblocks.values.toSet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 0d19f32cc6..1f3d56b5df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -428,6 +428,7 @@ class MultiblockShape { alias = "any solid copper block" ) fun copperGrate() = type(Material.COPPER_GRATE) + fun copperBulb() = type(Material.COPPER_BULB) fun fluidInput() = type(Material.FLETCHING_TABLE) fun titaniumBlock() = customBlock(CustomBlocks.TITANIUM_BLOCK) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index e6f4197b3b..0b8f728455 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -102,7 +102,7 @@ object PipedGasCollectorMultiblock : Multiblock(), FluidStoringEntity { override val capacities: Array = arrayOf( - loadStoredResource(data, "main", text("Main Gas Storage"), NamespacedKeys.GAS, CategoryRestrictedInternalStorage(500, FluidCategory.GAS)) + loadStoredResource(data, "main", text("Main Gas Storage"), NamespacedKeys.MAIN_STORAGE, CategoryRestrictedInternalStorage(500, FluidCategory.GAS)) ) override suspend fun tickAsync() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt new file mode 100644 index 0000000000..72a1548ad8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -0,0 +1,53 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid.storage + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.StorageContainer +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.UnlimitedInternalStorage +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.World +import org.bukkit.block.BlockFace + +abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityMultiblock { + override val name: String = "tank" + override val alternativeDetectionNames: Array = arrayOf("gastank", "fluidtank") + + override val signText: Array = arrayOf( + ofChildren(text("Fluid ", NamedTextColor.RED), text("Tank", NamedTextColor.GOLD)), + null, + null, + null + ) + + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): FluidStorageMultiblockEntity { + return FluidStorageMultiblockEntity(manager, this, data, x, y, z, world, structureDirection) + } + + class FluidStorageMultiblockEntity( + manager: ChunkMultiblockManager, + override val multiblock: FluidStorageMultiblock, + data: PersistentMultiblockData, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { + override val capacities: Array = arrayOf( + loadStoredResource(data, "main", text("Main Storage"), NamespacedKeys.MAIN_STORAGE, UnlimitedInternalStorage(multiblock.capacity)) + ) + + override fun storeAdditionalData(store: PersistentMultiblockData) { + val rawStorage = store.getAdditionalDataRaw() + storeStorageData(rawStorage, rawStorage.adapterContext) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankLarge.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankLarge.kt new file mode 100644 index 0000000000..344e759e44 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankLarge.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid.storage + +object FluidTankLarge { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt new file mode 100644 index 0000000000..8cfcc4dfba --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt @@ -0,0 +1,77 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid.storage + +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape + +object FluidTankMedium : FluidStorageMultiblock(75_000) { + override fun MultiblockShape.buildStructure() { + z(0) { + y(-1) { + x(-2).anyStairs() + x(-1).extractor() + x(+0).fluidInput() + x(+1).extractor() + x(+2).anyStairs() + } + y(+0) { + x(-2).anyCopperVariant() + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + x(+2).anyCopperVariant() + } + y(+1) { + x(-2).anyStairs() + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + x(+2).anyStairs() + } + } + z(1) { + y(-1) { + x(-2).anyCopperVariant() + x(-1).titaniumBlock() + x(+0).anyCopperBlock() + x(+1).titaniumBlock() + x(+2).anyCopperVariant() + } + y(+0) { + x(-2).copperBulb() + x(-1).anyGlass() + x(+0).anyGlass() + x(+1).anyGlass() + x(+2).copperBulb() + } + y(+1) { + x(-2).anyCopperVariant() + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + x(+2).anyCopperVariant() + } + } + z(2) { + y(-1) { + x(-2).anyStairs() + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + x(+2).anyStairs() + } + y(+0) { + x(-2).anyCopperVariant() + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + x(+2).anyCopperVariant() + } + y(+1) { + x(-2).anyStairs() + x(-1).titaniumBlock() + x(+0).anyCopperBlock() + x(+1).titaniumBlock() + x(+2).anyStairs() + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankSmall.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankSmall.kt new file mode 100644 index 0000000000..cbe001929a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankSmall.kt @@ -0,0 +1,44 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid.storage + +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape + +object FluidTankSmall : FluidStorageMultiblock(25_000) { + override fun MultiblockShape.buildStructure() { + z(0) { + y(-1) { + x(-1).anyStairs() + x(+0).fluidInput() + x(+1).anyStairs() + } + y(+0) { + x(-1).anyStairs() + x(+0).extractor() + x(+1).anyStairs() + } + } + z(1) { + y(-1) { + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + } + y(+0) { + x(-1).titaniumBlock() + x(+0).copperGrate() + x(+1).titaniumBlock() + } + } + z(2) { + y(-1) { + x(-1).anyStairs() + x(+0).anyCopperVariant() + x(+1).anyStairs() + } + y(+0) { + x(-1).anyStairs() + x(+0).anyCopperVariant() + x(+1).anyStairs() + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 5837c727a7..6f069b942b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -106,10 +106,9 @@ object NamespacedKeys { // Fluid storage val FLUID = key("fluid") - val CONTAINER_TYPE = key("container_type") val STORAGES = key("storages") - val FLUID_CATEGORIES = key("fluid_categories") + val MAIN_STORAGE = key("main_storage") fun key(key: String) = NamespacedKey(IonServer, key) From 8375b3b0ceff3c6c1b115400d84724fb65831e67 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 15:49:46 -0500 Subject: [PATCH 119/500] move more multiblocks over to the new registry, fix import --- .../command/starship/MiscStarshipCommands.kt | 2 - .../features/multiblock/MultiblockRecipes.kt | 228 ------------------ .../server/features/multiblock/Multiblocks.kt | 44 ++-- .../multiblock/crafting/MultiblockRecipes.kt | 52 ++-- .../newer/MultiblockRegistration.kt | 6 + .../multiblock/type/FurnaceMultiblock.kt | 2 +- .../multiblock/type/misc/ExpandableAirlock.kt | 4 +- .../miscellaneous/registrations/Components.kt | 2 +- 8 files changed, 50 insertions(+), 290 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRecipes.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index 3b45fa75e1..00f0cebce9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -34,8 +34,6 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.util.Pos import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.client.display.HudIcons -import net.horizonsend.ion.server.features.misc.HyperspaceBeaconManager -import net.horizonsend.ion.server.features.misc.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRecipes.kt deleted file mode 100644 index c290977f4e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRecipes.kt +++ /dev/null @@ -1,228 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting - -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ConsumedItemIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.GasCanisterIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ProgressHolderItemIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.ProcessingMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiRecipeResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressItemResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.SoundResult -import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.getMatchingMaterials -import org.bukkit.Material -import org.bukkit.SoundCategory -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.ItemStack -import java.util.LinkedList -import java.util.concurrent.ConcurrentHashMap - -@Suppress("UNUSED") -object MultiblockRecipes : IonServerComponent() { - private val recipes: ConcurrentHashMap>> = ConcurrentHashMap() - - val URANIUM_ENRICHMENT = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = CentrifugeMultiblock, - smelting = ConsumedItemIngredient(CustomItemRegistry.URANIUM, 1), - result = MultiRecipeResult( - ItemResult(CustomItemRegistry.ENRICHED_URANIUM), - SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - resources = listOf(power(100)), - ) - ) - - val URANIUM_CORE_COMPRESSION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = CompressorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.URANIUM_CORE, 1), progressHolderResult = CustomItemRegistry.URANIUM_ROD), - resources = listOf(power(100)), - result = MultiRecipeResult( - ProgressItemResult(CustomItemRegistry.URANIUM_ROD, 60L * 60L * 20L, SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - ) - - val STEEL_PRODUCTION = registerRecipe( - FurnaceMultiblockRecipe( - multiblock = GasFurnaceMultiblock, - smelting = ConsumedItemIngredient(ItemStack(Material.IRON_INGOT), 1), - fuel = GasCanisterIngredient(CustomItemRegistry.GAS_CANISTER_OXYGEN, 5), - resources = listOf(power(100)), - result = ItemResult(CustomItemRegistry.STEEL_INGOT) - ) - ) - - val REACTIVE_PLATING_PRESSING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = PlatePressMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.REACTIVE_PLATING, 1), progressHolderResult = CustomItemRegistry.REACTIVE_CHASSIS), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.REACTIVE_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val STEEL_PLATE_PRESSING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = PlatePressMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.STEEL_PLATE, 1), progressHolderResult = CustomItemRegistry.STEEL_CHASSIS), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.STEEL_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val FUEL_ROD_CORE_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.FUEL_ROD_CORE, 1), progressHolderResult = CustomItemRegistry.FUEL_CELL), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.FUEL_CELL, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val FABRICATED_ASSEMBLY_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.REACTIVE_ASSEMBLY, 1), progressHolderResult = CustomItemRegistry.FABRICATED_ASSEMBLY), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.FABRICATED_ASSEMBLY, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val REINFORCED_FRAME_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.STEEL_ASSEMBLY, 1), progressHolderResult = CustomItemRegistry.REINFORCED_FRAME), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.REINFORCED_FRAME, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val CIRCUIT_BOARD_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = CircuitfabMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.CIRCUITRY, 1), progressHolderResult = CustomItemRegistry.CIRCUIT_BOARD), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.CIRCUIT_BOARD, 60L * 60L * 20L, SoundResult("horizonsend:industry.cirfab", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val LOADED_SHELL_LOADING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = AmmoLoaderMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.UNLOADED_SHELL, 1), progressHolderResult = CustomItemRegistry.LOADED_SHELL), - resources = listOf(power(100)), - result = MultiRecipeResult(ProgressItemResult(CustomItemRegistry.LOADED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f))) - ) - ) - - val UNCHARGED_SHELL_CHARGING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = AmmoLoaderMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.UNCHARGED_SHELL, 1), progressHolderResult = CustomItemRegistry.CHARGED_SHELL), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.CHARGED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val ARSENAL_MISSILE_LOADING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = MissileLoaderMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItemRegistry.UNLOADED_ARSENAL_MISSILE, 1), progressHolderResult = CustomItemRegistry.ARSENAL_MISSILE), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItemRegistry.ARSENAL_MISSILE, 60L * 60L * 20L, SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - //BC recipies end - - //misc recipies start - - val COPPER_OXIDATION = registerAllMatch( - "^(WAXED_|)(CUT|)(_?)(COPPER_BLOCK|COPPER)(.*)", - setOf(Material.COPPER_ORE, - Material.DEEPSLATE_COPPER_ORE, - Material.COPPER_INGOT), - "^(WAXED_|)(EXPOSED)(.*)", - "\$1EXPOSED\$3\$2_COPPER\$5" - ) - - val EXPOSED_COPPER_OXIDATION = registerAllMatch( - "^(WAXED_|)(EXPOSED)(.*)", - setOf(), - "^(WAXED_|)(WEATHERED)(.*)", - "\$1WEATHERED\$3" - ) - - val WEATHERED_COPPER_OXIDATION = registerAllMatch( - "^(WAXED_|)(WEATHERED)(.*)", - setOf(), - "^(WAXED_|)(OXIDIZED)(.*)", - "\$1OXIDIZED\$3" - ) - - /** - * Add a power ingredient - **/ - private fun power(amount: Int) = ResourceIngredient(NamespacedKeys.POWER, amount) - - private fun registerRecipe(recipe: MultiblockRecipe): MultiblockRecipe { - recipes.getOrPut(recipe.multiblock) { LinkedList() }.add(recipe) - - return recipe - } - - private fun registerAllMatch( - inputMatch: String, ignore : Set, outputMatch : String, replaceStr : String - ): Set> { - val recipes = mutableSetOf>() - val inputMatches = run { - val list: MutableSet = getMatchingMaterials { it.name.matches(Regex(inputMatch)) } - list.removeAll(ignore) - list.toSet() - } - - val outputMatches = run { - val list: MutableSet = getMatchingMaterials { it.name.matches(Regex(outputMatch)) } - list.toSet() - } - - for (inputMat in inputMatches) { - val resultMat = outputMatches.first { it.name == inputMat.name.replace(Regex(inputMatch),replaceStr) } - val recipe = registerRecipe( - FurnaceMultiblockRecipe( - multiblock = GasFurnaceMultiblock, - smelting = ConsumedItemIngredient(ItemStack(inputMat), 1), - fuel = GasCanisterIngredient(CustomItemRegistry.GAS_CANISTER_OXYGEN, 50), - resources = listOf(power(100)), - result = ItemResult(ItemStack(resultMat)) - ) - ) - recipes.add(recipe) - } - return recipes.toSet() - } - - fun getRecipe(multiblock: T, sign: Sign, inventory: Inventory): MultiblockRecipe? { - @Suppress("UNCHECKED_CAST") - val recipesFor = (recipes[multiblock] as? LinkedList>) ?: return null - - return recipesFor.firstOrNull { it.matches(sign, inventory) } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt index dfce587e93..7ddd7b5489 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt @@ -8,17 +8,16 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.achievements.Achievement -import net.horizonsend.ion.server.features.achievements.rewardAchievement +import net.horizonsend.ion.server.command.misc.MultiblockCommand.setupCommand +import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Bottom +import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Side +import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Top import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 @@ -29,12 +28,9 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.Har import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock -import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.gravitywell.AmplifiedGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.gravitywell.StandardGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock @@ -52,17 +48,15 @@ import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLa import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Bottom import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Side import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Top -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier4Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier4Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier4Top -import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock -import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 @@ -73,7 +67,9 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterM import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -130,18 +126,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(GlassPrinterMultiblock) registerMultiblock(ArmorPrinterMultiblock) - registerMultiblock(DisconnectedDockingTubeMultiblock) - registerMultiblock(ConnectedDockingTubeMultiblock) - - registerMultiblock(CryoPodMultiblock) - registerMultiblock(FuelTankMultiblock) - registerMultiblock(MagazineMultiblock) - registerMultiblock(AirlockMultiblock) - registerMultiblock(ExpandableAirlock) - registerMultiblock(TractorBeamMultiblock) - - registerMultiblock(ShipFactoryMultiblock) - registerMultiblock(DrillMultiblockTier1) registerMultiblock(DrillMultiblockTier2) registerMultiblock(DrillMultiblockTier3) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt index 55b56af563..a12709ed92 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt @@ -35,7 +35,7 @@ import java.util.concurrent.ConcurrentHashMap object MultiblockRecipes : IonServerComponent() { private val recipes: ConcurrentHashMap>> = ConcurrentHashMap() - val URANIUM_ENRICHMENT = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val URANIUM_ENRICHMENT = registerRecipe( ProcessingMultiblockRecipe( multiblock = CentrifugeMultiblock, smelting = ConsumedItemIngredient(CustomItems.URANIUM, 1), @@ -43,108 +43,108 @@ object MultiblockRecipes : IonServerComponent() { ItemResult(CustomItems.ENRICHED_URANIUM), SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) ), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), ) ) - val URANIUM_CORE_COMPRESSION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val URANIUM_CORE_COMPRESSION = registerRecipe( ProcessingMultiblockRecipe( multiblock = CompressorMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.URANIUM_CORE, 1), progressHolderResult = CustomItems.URANIUM_ROD), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = MultiRecipeResult( ProgressItemResult(CustomItems.URANIUM_ROD, 60L * 60L * 20L, SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) ) - val STEEL_PRODUCTION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val STEEL_PRODUCTION = registerRecipe( FurnaceMultiblockRecipe( multiblock = GasFurnaceMultiblock, smelting = ConsumedItemIngredient(ItemStack(Material.IRON_INGOT), 1), fuel = GasCanisterIngredient(CustomItems.GAS_CANISTER_OXYGEN, 5), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ItemResult(CustomItems.STEEL_INGOT) ) ) - val REACTIVE_PLATING_PRESSING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val REACTIVE_PLATING_PRESSING = registerRecipe( ProcessingMultiblockRecipe( multiblock = PlatePressMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.REACTIVE_PLATING, 1), progressHolderResult = CustomItems.REACTIVE_CHASSIS), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.REACTIVE_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val STEEL_PLATE_PRESSING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val STEEL_PLATE_PRESSING = registerRecipe( ProcessingMultiblockRecipe( multiblock = PlatePressMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.STEEL_PLATE, 1), progressHolderResult = CustomItems.STEEL_CHASSIS), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.STEEL_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val FUEL_ROD_CORE_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val FUEL_ROD_CORE_FABRICATION = registerRecipe( ProcessingMultiblockRecipe( multiblock = FabricatorMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.FUEL_ROD_CORE, 1), progressHolderResult = CustomItems.FUEL_CELL), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.FUEL_CELL, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val FABRICATED_ASSEMBLY_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val FABRICATED_ASSEMBLY_FABRICATION = registerRecipe( ProcessingMultiblockRecipe( multiblock = FabricatorMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.REACTIVE_ASSEMBLY, 1), progressHolderResult = CustomItems.FABRICATED_ASSEMBLY), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.FABRICATED_ASSEMBLY, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val REINFORCED_FRAME_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val REINFORCED_FRAME_FABRICATION = registerRecipe( ProcessingMultiblockRecipe( multiblock = FabricatorMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.STEEL_ASSEMBLY, 1), progressHolderResult = CustomItems.REINFORCED_FRAME), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.REINFORCED_FRAME, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val CIRCUIT_BOARD_FABRICATION = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val CIRCUIT_BOARD_FABRICATION = registerRecipe( ProcessingMultiblockRecipe( multiblock = CircuitfabMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.CIRCUITRY, 1), progressHolderResult = CustomItems.CIRCUIT_BOARD), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.CIRCUIT_BOARD, 60L * 60L * 20L, SoundResult("horizonsend:industry.cirfab", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val LOADED_SHELL_LOADING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val LOADED_SHELL_LOADING = registerRecipe( ProcessingMultiblockRecipe( multiblock = AmmoLoaderMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNLOADED_SHELL, 1), progressHolderResult = CustomItems.LOADED_SHELL), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = MultiRecipeResult(ProgressItemResult(CustomItems.LOADED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f))) ) ) - val UNCHARGED_SHELL_CHARGING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val UNCHARGED_SHELL_CHARGING = registerRecipe( ProcessingMultiblockRecipe( multiblock = AmmoLoaderMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNCHARGED_SHELL, 1), progressHolderResult = CustomItems.CHARGED_SHELL), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.CHARGED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) - val ARSENAL_MISSILE_LOADING = net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.registerRecipe( + val ARSENAL_MISSILE_LOADING = registerRecipe( ProcessingMultiblockRecipe( multiblock = MissileLoaderMultiblock, smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNLOADED_ARSENAL_MISSILE, 1), progressHolderResult = CustomItems.ARSENAL_MISSILE), - resources = listOf(net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.power(100)), + resources = listOf(power(100)), result = ProgressItemResult(CustomItems.ARSENAL_MISSILE, 60L * 60L * 20L, SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f)) ) ) @@ -155,14 +155,14 @@ object MultiblockRecipes : IonServerComponent() { private fun power(amount: Int) = ResourceIngredient(NamespacedKeys.POWER, amount) private fun registerRecipe(recipe: MultiblockRecipe): MultiblockRecipe { - net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.recipes.getOrPut(recipe.multiblock) { LinkedList() }.add(recipe) + recipes.getOrPut(recipe.multiblock) { LinkedList() }.add(recipe) return recipe } fun getRecipe(multiblock: T, sign: Sign, inventory: Inventory): MultiblockRecipe? { @Suppress("UNCHECKED_CAST") - val recipesFor = (net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes.recipes[multiblock] as? LinkedList>) ?: return null + val recipesFor = (recipes[multiblock] as? LinkedList>) ?: return null return recipesFor.firstOrNull { it.matches(sign, inventory) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index babb10267e..90892c340d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -24,11 +24,13 @@ import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.Hyperdrive import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass4 import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced @@ -193,11 +195,15 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(BoxShieldMultiblock) registerMultiblock(EventShieldMultiblock) + // Machine + registerMultiblock(ShipFactoryMultiblock) + // Misc registerMultiblock(DisconnectedDockingTubeMultiblock) registerMultiblock(ConnectedDockingTubeMultiblock) registerMultiblock(CryoPodMultiblock) registerMultiblock(AirlockMultiblock) + registerMultiblock(ExpandableAirlock) registerMultiblock(TractorBeamMultiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt index dc6767d73f..9f92810396 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockRecipes +import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceEventHandler import org.bukkit.block.Furnace import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ExpandableAirlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ExpandableAirlock.kt index 5544c03038..12469f3840 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ExpandableAirlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ExpandableAirlock.kt @@ -4,10 +4,10 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 8a4a876ac8..403c45dfea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -37,8 +37,8 @@ import net.horizonsend.ion.server.features.misc.GameplayTweaks import net.horizonsend.ion.server.features.misc.ProxyMessaging import net.horizonsend.ion.server.features.misc.Shuttles import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge -import net.horizonsend.ion.server.features.multiblock.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes From ca690dcbde866cde55f1e7bb6b9c4a5cb9b59166 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 16:47:13 -0500 Subject: [PATCH 120/500] build out more storage code --- .../server/features/multiblock/PrePackaged.kt | 6 +- .../CategoryRestrictedInternalStorage.kt | 2 +- .../entity/type/fluids/FluidStoringEntity.kt | 11 +- .../entity/type/fluids/InternalStorage.kt | 65 +++++-- .../entity/type/fluids/StorageContainer.kt | 6 +- .../type/fluids/UnlimitedInternalStorage.kt | 2 +- .../collector/PipedGasCollectorMultiblock.kt | 2 +- .../transport/container/ItemContainer.kt | 4 - .../container/NamespacedResourceContainer.kt | 173 ------------------ .../transport/container/ResourceContainer.kt | 28 --- .../persistence/NamespacedKeys.kt | 4 +- 11 files changed, 69 insertions(+), 234 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index cf79873470..6325313c95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -100,6 +102,8 @@ object PrePackaged { sign.getSide(Side.FRONT).line(0, text("[${data.multiblock.name}]")) sign.update() + MultiblockAccess.tryDetectMultiblock(player, sign, direction, false) + data.multiblock.setupSign(player, sign) } @@ -111,7 +115,7 @@ object PrePackaged { val data = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER) ?: return null //TODO rework for player packaged items val storageName = data.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING)!! - val multiblock = Multiblocks.getMultiblockByName(storageName) + val multiblock = MultiblockRegistration.getByStorageName(storageName)!! return PackagedMultiblockData(multiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt index fa18d6019c..341265a4c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt @@ -9,7 +9,7 @@ class CategoryRestrictedInternalStorage( ) : InternalStorage() { override fun getCapacity(): Int = storageCapacity - override fun canStore(resource: PipedFluid, liters: Double): Boolean { + override fun canStore(resource: PipedFluid, liters: Int): Boolean { if (liters + getAmount() > getCapacity()) { return false } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 9dfa06bf93..5f875184de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -12,11 +12,16 @@ import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { val capacities: Array - fun canStore(fluid: PipedFluid, amount: Double) = capacities.any { it.storage.canStore(fluid, amount) } + fun canStore(fluid: PipedFluid, amount: Int) = capacities.any { it.storage.canStore(fluid, amount) } - fun firstCasStore(fluid: PipedFluid, amount: Double): StorageContainer? = capacities.firstOrNull { it.storage.canStore(fluid, amount) } + fun firstCasStore(fluid: PipedFluid, amount: Int): StorageContainer? = capacities.firstOrNull { it.storage.canStore(fluid, amount) } + + fun getStoredResources() : Map = capacities.associate { it.storage.getStoredFluid() to it.storage.getAmount() } + + fun getNamedStorage(name: String): StorageContainer = capacities.first { it.name == name } + + fun getStorage(key: NamespacedKey): StorageContainer = capacities.first { it.namespacedKey == key } - fun getStoredResources() : Map = capacities.associate { it.storage.getStoredFluid() to it.storage.getAmount().toDouble() } fun storeStorageData(destination: PersistentDataContainer, context: PersistentDataAdapterContext) { val storages = context.newPersistentDataContainer() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt index 396ea01ab2..9e60843f6b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt @@ -15,24 +15,51 @@ abstract class InternalStorage { protected var amountUnsafe: Int = 0 protected var fluidUnsafe: PipedFluid? = null - abstract fun canStore(resource: PipedFluid, liters: Double): Boolean - abstract fun getCapacity(): Int - fun getStoredFluid(): PipedFluid? = fluidUnsafe + abstract fun canStore(resource: PipedFluid, liters: Int): Boolean + + fun isEmpty(): Boolean = getStoredFluid() == null || getAmount() == 0 + + fun isFull(): Boolean = getStoredFluid() != null && getAmount() == getCapacity() + + fun remove(amount: Int): Int { + val newTotal = getAmount() - amount + // negative total will be a remainder + val notRemoved = if (newTotal < 0) -newTotal else 0 + + setAmount(newTotal) + + return notRemoved + } + + fun remove(fluid: PipedFluid, amount: Int): Int { + if (getStoredFluid() != null && fluid != getStoredFluid()) return amount + + if (getStoredFluid() == null) setFluid(fluid) + + return remove(amount) + } + + fun addAmount(amount: Int): Int { + val newTotal = getAmount() + amount + val notAdded = if (newTotal > getCapacity()) newTotal - getCapacity() else 0 - fun addAmount(amount: Int) { setAmount(getAmount() + amount) + + return notAdded } - fun addAmount(fluid: PipedFluid, amount: Int) { - if (getStoredFluid() != null && fluid != getStoredFluid()) return + fun addAmount(fluid: PipedFluid, amount: Int): Int { + if (getStoredFluid() != null && fluid != getStoredFluid()) return amount if (getStoredFluid() == null) setFluid(fluid) - addAmount(amount) + return addAmount(amount) } + fun getStoredFluid(): PipedFluid? = fluidUnsafe + fun getAmount(): Int = amountUnsafe fun setContents(fluid: PipedFluid, amount: Int) { @@ -46,35 +73,35 @@ abstract class InternalStorage { this.amountUnsafe = corrected if (corrected == 0) setFluid(null) - - updateVisually() } fun setFluid(fluid: PipedFluid?) { this.fluidUnsafe = fluid - - updateVisually() } - open fun updateVisually() {} - - fun getContents(): Pair = fluidUnsafe to getAmount() - - open fun saveAdditionalData(pdc: PersistentDataContainer) {} - + /** + * Load storage data from the provided persistent data container + **/ fun loadData(pdc: PersistentDataContainer) { val fluid = pdc.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } - val amount = pdc.getOrDefault(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, 0) + val amount = pdc.getOrDefault(NamespacedKeys.FLUID_AMOUNT, PersistentDataType.INTEGER, 0) setFluid(fluid) setAmount(amount) } + /** + * Save storage data to the provided persistent data container + **/ fun saveData(destination: PersistentDataContainer) { val fluid = getStoredFluid() ?: return val amount = getAmount() destination.set(NamespacedKeys.FLUID, PersistentDataType.STRING, fluid.identifier) - destination.set(NamespacedKeys.RESOURCE_AMOUNT, PersistentDataType.INTEGER, amount) + destination.set(NamespacedKeys.FLUID_AMOUNT, PersistentDataType.INTEGER, amount) + } + + override fun toString(): String { + return "${javaClass.simpleName}[capacity= ${getCapacity()} fluid= (${getStoredFluid()}, ${getAmount()})]" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt index 936c228a1b..9375a71f69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt @@ -8,7 +8,7 @@ import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER class StorageContainer( val name: String, val displayName: Component, - private val namespacedKey: NamespacedKey, + val namespacedKey: NamespacedKey, val storage: InternalStorage ) { fun save(destination: PersistentDataContainer) { @@ -17,4 +17,8 @@ class StorageContainer( destination.set(namespacedKey, TAG_CONTAINER, pdc) } + + override fun toString(): String { + return "Container[name= $name, key= $namespacedKey, storage= $storage]" + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt index 5a092735c5..8826a3946a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.transport.fluids.PipedFluid class UnlimitedInternalStorage(private val storageCapacity: Int) : InternalStorage() { override fun getCapacity(): Int = storageCapacity - override fun canStore(resource: PipedFluid, liters: Double): Boolean { + override fun canStore(resource: PipedFluid, liters: Int): Boolean { if (liters + getAmount() > getCapacity()) return false // Check that the fluid attempting to be stored is the same as the one currently stored diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 0b8f728455..3a30dd8b86 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -106,7 +106,7 @@ object PipedGasCollectorMultiblock : Multiblock(), ) override suspend fun tickAsync() { - firstCasStore(HYDROGEN, 1.0)?.storage?.addAmount(HYDROGEN, 1) + firstCasStore(HYDROGEN, 1)?.storage?.addAmount(HYDROGEN, 1) } override fun storeAdditionalData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt deleted file mode 100644 index b50fe44ace..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ItemContainer.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.container - -//class ItemContainer : ResourceContainer { TODO -//} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt deleted file mode 100644 index 8527fbb1ac..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/NamespacedResourceContainer.kt +++ /dev/null @@ -1,173 +0,0 @@ -package net.horizonsend.ion.server.features.transport.container - -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_AMOUNT -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_CAPACITY_MAX -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.RESOURCE_CAPACITY_MIN -import org.bukkit.NamespacedKey -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType.INTEGER -import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER -import java.util.concurrent.ConcurrentHashMap - -class NamespacedResourceContainer( - val resourceData: Map -) : ResourceContainer { - val stored: MutableMap = ConcurrentHashMap() - - fun getCapacity(resource: NamespacedKey): Int { - verifyKey(resource) - - return resourceData[resource]!!.maxAmount - } - - fun getMinimumAmount(resource: NamespacedKey): Int { - verifyKey(resource) - - return resourceData[resource]!!.minAmount - } - - override fun getContents(): Map { - return stored - } - - override fun getAmount(resource: NamespacedKey): Int { - verifyKey(resource) - - return stored.getOrPut(resource) { 0 } - } - - override fun setAmount(resource: NamespacedKey, amount: Int) { - verifyKey(resource) - - val corrected = coerce(resource, amount) - - stored[resource] = corrected - } - - /** - * Returns the amount of power that could not be added - **/ - override fun add(resource: NamespacedKey, amount: Int): Int { - verifyKey(resource) - - val current = getAmount(resource) - - val newAmount = current + amount - - setAmount(resource, newAmount) - - val maximum = getCapacity(resource) - - return if (newAmount > maximum) maximum - newAmount else 0 - } - - /** - * Returns the amount of power that could not be removed - **/ - override fun remove(resource: NamespacedKey, amount: Int): Int { - verifyKey(resource) - - val newAmount = getAmount(resource) - amount - - setAmount(resource, newAmount) - - val minimum = getMinimumAmount(resource) - - return if (newAmount < minimum) newAmount else minimum - } - - override fun canFit(resource: NamespacedKey, amount: Int): Boolean { - verifyKey(resource) - - val current = getAmount(resource) - val maximum = getCapacity(resource) - - return current + amount <= maximum - } - - override fun canRemove(resource: NamespacedKey, amount: Int): Boolean { - verifyKey(resource) - - val current = getAmount(resource) - val minimum = getMinimumAmount(resource) - - return current - amount >= minimum - } - - private fun coerce(resource: NamespacedKey, amount: Int): Int { - verifyKey(resource) - - val max = getCapacity(resource) - val min = getCapacity(resource) - - return amount.coerceIn(min..max) - } - - /** - * Verifies that the provided key is part of this container - **/ - private fun verifyKey(key: NamespacedKey) { - if (!resourceData.containsKey(key)) throw IllegalArgumentException("Container does not contain resource $key") - } - - override fun serialize(context: PersistentDataAdapterContext): PersistentDataContainer { - val pdc = context.newPersistentDataContainer() - - for ((key, data) in resourceData) { - val resourcePDC = context.newPersistentDataContainer() - - resourcePDC.set(RESOURCE_CAPACITY_MAX, INTEGER, data.maxAmount) - resourcePDC.set(RESOURCE_CAPACITY_MIN, INTEGER, data.minAmount) - resourcePDC.set(RESOURCE_AMOUNT, INTEGER, stored.getOrDefault(key, 0)) - - pdc.set(key, TAG_CONTAINER, resourcePDC) - } - - return pdc - } - - companion object { - fun deserialize(data: PersistentDataContainer): NamespacedResourceContainer { - val resourcePDCs = data.keys.associateWith { resource -> - data.get(resource, TAG_CONTAINER)!! - } - - val resourceData = resourcePDCs.mapValues { (_, pdc) -> - ResourceData( - maxAmount = pdc.get(RESOURCE_CAPACITY_MAX, INTEGER)!!, - minAmount = pdc.get(RESOURCE_CAPACITY_MIN, INTEGER)!! - ) - } - - val container = NamespacedResourceContainer(resourceData) - - resourcePDCs.entries.forEach { (resource) -> - container.setAmount(resource, resourcePDCs[resource]!!.get(RESOURCE_AMOUNT, INTEGER)!!) - } - - return container - } - - fun powerContainer(maxPower: Int): NamespacedResourceContainer = - NamespacedResourceContainer(mapOf(NamespacedKeys.POWER to ResourceData(minAmount = 0, maxAmount = maxPower))) - } - - data class ResourceData( - val maxAmount: Int, - val minAmount: Int = 0, - ) - - class Builder { - private val resources: MutableMap = mutableMapOf() - - fun addResource(key: NamespacedKey, max: Int, min: Int = 0) : Builder { - resources[key] = ResourceData(max, min) - - return this - } - - fun build(): NamespacedResourceContainer = NamespacedResourceContainer(resources) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt deleted file mode 100644 index 978d82cfb9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/container/ResourceContainer.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.horizonsend.ion.server.features.transport.container - -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer - -/** - * A container that holds transferable resources - **/ -interface ResourceContainer { - /** - * Get transferable resources and their amounts - **/ - fun getContents(): Map - - fun getAmount(resource: T): Int - - fun setAmount(resource: T, amount: Int) - - fun canRemove(resource: T, amount: Int): Boolean - - fun canFit(resource: T, amount: Int): Boolean - - fun add(resource: T, amount: Int): Int - - fun remove(resource: T, amount: Int): Int - - fun serialize(context: PersistentDataAdapterContext): PersistentDataContainer -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 6f069b942b..44b927e7cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -89,14 +89,13 @@ object NamespacedKeys { val RESOURCE_CAPACITY_MAX = key("resource_capacity_max") val RESOURCE_CAPACITY_MIN = key("resource_capacity_min") - val RESOURCE_AMOUNT = key("resource_amount") val PROCESSING_PROGRESS = key("processing_progress") val NODE_COVERED_POSITIONS = key("node_covered_positions") val AXIS = key("axis") val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") - val SOLAR_CELL_DETECTORS = key("solar_cell_extractors") + val SOLAR_CELL_DETECTORS = key("solar_cell_detectors") val NODE_TYPE = key("node_type") @@ -106,6 +105,7 @@ object NamespacedKeys { // Fluid storage val FLUID = key("fluid") + val FLUID_AMOUNT = key("fluid_amount") val STORAGES = key("storages") val MAIN_STORAGE = key("main_storage") From 4b6dbcdfd8ffbadccce8a040c61cca478dfa1a68 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 30 Aug 2024 17:01:31 -0500 Subject: [PATCH 121/500] cleanup, make class to handle simple fluid storage cases --- .../type/fluids/BasicFluidStoringEntity.kt | 37 +++++++++++++++++++ .../collector/PipedGasCollectorMultiblock.kt | 20 ++-------- .../fluid/storage/FluidStorageMultiblock.kt | 15 +------- 3 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt new file mode 100644 index 0000000000..0e560524a6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -0,0 +1,37 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.kyori.adventure.text.Component +import org.bukkit.World +import org.bukkit.block.BlockFace + +/** + * A simple fluid storing entity with a single main storage + **/ +abstract class BasicFluidStoringEntity( + manager: ChunkMultiblockManager, + multiblock: Multiblock, + data: PersistentMultiblockData, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + storage: InternalStorage +) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { + @Suppress("LeakingThis") + override val capacities: Array = arrayOf( + loadStoredResource(data, "main", Component.text("Main Storage"), NamespacedKeys.MAIN_STORAGE, storage) + ) + + val mainStorage by lazy { getStorage(NamespacedKeys.MAIN_STORAGE) } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + val rawStorage = store.getAdditionalDataRaw() + storeStorageData(rawStorage, rawStorage.adapterContext) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 3a30dd8b86..fa7a94072e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -3,19 +3,17 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.collector import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.CategoryRestrictedInternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.StorageContainer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GOLD @@ -97,23 +95,16 @@ object PipedGasCollectorMultiblock : Multiblock(), z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, PipedGasCollectorMultiblock, x, y, z, world, structureDirection), + ) : BasicFluidStoringEntity(manager, PipedGasCollectorMultiblock, data, x, y, z, world, structureDirection, CategoryRestrictedInternalStorage(500, FluidCategory.GAS)), AsyncTickingMultiblockEntity, FluidStoringEntity { - override val capacities: Array = arrayOf( - loadStoredResource(data, "main", text("Main Gas Storage"), NamespacedKeys.MAIN_STORAGE, CategoryRestrictedInternalStorage(500, FluidCategory.GAS)) - ) + private var lastTicked: Long = System.currentTimeMillis() override suspend fun tickAsync() { firstCasStore(HYDROGEN, 1)?.storage?.addAmount(HYDROGEN, 1) } - override fun storeAdditionalData(store: PersistentMultiblockData) { - val rawStorage = store.getAdditionalDataRaw() - storeStorageData(rawStorage, rawStorage.adapterContext) - } - override fun onLoad() { } @@ -127,10 +118,7 @@ object PipedGasCollectorMultiblock : Multiblock(), } override fun toString(): String { - return """ - Piped gas collector :) - Storage: ${getStoredResources()} - """.trimIndent() + return "Piped gas collector. Storage: $mainStorage" } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 72a1548ad8..3d404735ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -2,14 +2,12 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.storage import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.StorageContainer import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.UnlimitedInternalStorage import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor @@ -40,14 +38,5 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { - override val capacities: Array = arrayOf( - loadStoredResource(data, "main", text("Main Storage"), NamespacedKeys.MAIN_STORAGE, UnlimitedInternalStorage(multiblock.capacity)) - ) - - override fun storeAdditionalData(store: PersistentMultiblockData) { - val rawStorage = store.getAdditionalDataRaw() - storeStorageData(rawStorage, rawStorage.adapterContext) - } - } + ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity } From 8390b4c06c6141ece42ba5198894c7591c3def3f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 12:15:34 -0500 Subject: [PATCH 122/500] misc --- .../type/power/SimpleTextDisplayPoweredMultiblockEntity.kt | 2 +- .../type/fluid/collector/PipedGasCollectorMultiblock.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt index 12fc21b1fb..aefd615a90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt @@ -18,7 +18,7 @@ interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity, Di } companion object { - fun createTextDisplayHandler(entity: SimpleTextDisplayPoweredMultiblockEntity): TextDisplayHandler { + fun createTextDisplayHandler(entity: DisplayHandlerHolder): TextDisplayHandler { require(entity is MultiblockEntity) val signDirection = entity.structureDirection.oppositeFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index fa7a94072e..e845dfd192 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -102,7 +102,7 @@ object PipedGasCollectorMultiblock : Multiblock(), private var lastTicked: Long = System.currentTimeMillis() override suspend fun tickAsync() { - firstCasStore(HYDROGEN, 1)?.storage?.addAmount(HYDROGEN, 1) + mainStorage.storage.addAmount(HYDROGEN, 1) } override fun onLoad() { From ec1b5e14a58202a3bce20c59ee06b62399ea1635 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 13:38:47 -0500 Subject: [PATCH 123/500] multiblock place improvements --- .../server/command/misc/MultiblockCommand.kt | 4 +- .../server/features/multiblock/PrePackaged.kt | 2 +- .../multiblock/shape/BlockRequirement.kt | 11 +++- .../multiblock/shape/MultiblockShape.kt | 59 ++++++++++++++----- .../NavigationComputerMultiblockAdvanced.kt | 29 +++++---- .../multiblock/util/PrepackagedPreset.kt | 30 ++++++++++ .../utils/coordinates/RelativeFace.kt | 30 ++++++++++ 7 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index d8cf6128f1..448d752ac4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -104,7 +104,7 @@ object MultiblockCommand : SLCommand() { if (!requirementMet) { val (xx, yy, zz) = Vec3i(relative.location) - sendEntityPacket(sender, displayBlock(sender.world.minecraft, expected, Vector(xx, yy, zz), 0.5f, true), 10 * 20L) + sendEntityPacket(sender, displayBlock(sender.world.minecraft, expected.invoke(face), Vector(xx, yy, zz), 0.5f, true), 10 * 20L) sender.userError( "Block at ${Vec3i(relative.location)} doesn't match! Expected ${requirement.alias}, found ${relative.type}." ) @@ -141,7 +141,7 @@ object MultiblockCommand : SLCommand() { if (!event) return sender.userError("You can't build here!") - existingBlock.blockData = blockData + existingBlock.blockData = blockData.invoke(sender.facing) } sender.success("Placed ${multiblock.javaClass.simpleName}") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 6325313c95..2c2bff18e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -79,7 +79,7 @@ object PrePackaged { if (!event) return player.userError("You can't build here!") - placements[existingBlock] = requirement.example + placements[existingBlock] = requirement.example.invoke(direction) } for ((block, placement) in placements) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 2aa9d4b244..155c864a7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -1,12 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.shape +import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData class BlockRequirement( val alias: String, - var example: BlockData, + var example: (BlockFace) -> BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean ) { @@ -15,7 +16,13 @@ class BlockRequirement( suspend fun checkAsync(block: Block, inward: BlockFace, loadChunks: Boolean) = asyncCheck.invoke(block, inward, loadChunks) fun setExample(blockData: BlockData): BlockRequirement { - this.example = blockData + this.example = { blockData } + + return this + } + + fun setExample(type: Material): BlockRequirement { + this.example = { type.createBlockData() } return this } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 1f3d56b5df..8907127c1d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -265,7 +265,7 @@ class MultiblockShape { fun type(type: Material) { val requirement = BlockRequirement( alias = type.toString(), - example = type.createBlockData(), + example = { type.createBlockData() }, syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type } ) @@ -278,7 +278,7 @@ class MultiblockShape { val requirement = BlockRequirement( alias = alias, - example = types.first().createBlockData(), + example = { types.first().createBlockData() }, syncCheck = { block, _, loadChunks -> typeSet.contains(if (loadChunks) block.type else block.getTypeSafe()) }, @@ -297,7 +297,7 @@ class MultiblockShape { fun customBlock(customBlock: CustomBlock) { val requirement = BlockRequirement( alias = customBlock.identifier, - example = customBlock.blockData, + example = { customBlock.blockData }, syncCheck = { block, _, loadChunks -> if (loadChunks) CustomBlocks.getByBlock(block) else { getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } @@ -336,21 +336,27 @@ class MultiblockShape { fun seaLantern() = type(Material.SEA_LANTERN) fun glassPane() = type(Material.GLASS_PANE) fun stainedGlassPane() = filteredTypes("any stained glass pane") { it.isStainedGlassPane } - fun anyGlassPane() = filteredTypes("any stained glass") { it.isGlassPane } + fun anyGlassPane(edit: BlockRequirement.() -> Unit = {}) = filteredTypes("any stained glass", edit = edit) { it.isGlassPane } - fun anyStairs() = filteredTypes("any stair block", edit = { setExample(Material.STONE_BRICK_STAIRS.createBlockData()) }) { it.isStairs } + fun anyStairs(edit: BlockRequirement.() -> Unit = { setExample(Material.STONE_BRICK_STAIRS.createBlockData()) }) = + filteredTypes("any stair block", edit) { it.isStairs } - fun anyWall() = filteredTypes("any wall block", edit = { setExample(Material.STONE_BRICK_WALL.createBlockData()) }) { it.isWall } + fun anyWall(edit: BlockRequirement.() -> Unit = { setExample(Material.STONE_BRICK_WALL.createBlockData()) }) = + filteredTypes("any wall block", edit) { it.isWall } fun anyWool() = filteredTypes("any wool block") { it.isWool } - fun anySlab() = filteredTypes("any slab block", edit = { setExample(Material.STONE_BRICK_SLAB.createBlockData()) }) { it.isSlab } + fun anySlab(edit: BlockRequirement.() -> Unit = { setExample(Material.STONE_BRICK_SLAB.createBlockData()) }) = + filteredTypes("any slab block", edit) { it.isSlab } + fun anyDoubleSlab() = complete( BlockRequirement( alias = "any double slab block", - example = Material.STONE_BRICK_SLAB.createBlockData().apply { - this as Slab - this.type = Slab.Type.DOUBLE + example = { + Material.STONE_BRICK_SLAB.createBlockData().apply { + this as Slab + this.type = Slab.Type.DOUBLE + } }, syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) @@ -368,7 +374,7 @@ class MultiblockShape { fun terracottaOrDoubleslab() { BlockRequirement( alias = "any double slab or terracotta block", - example = Material.CYAN_TERRACOTTA.createBlockData(), + example = { Material.CYAN_TERRACOTTA.createBlockData() }, syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) val blockType = if (loadChunks) block.type else block.getTypeSafe() @@ -427,8 +433,28 @@ class MultiblockShape { Material.WAXED_OXIDIZED_COPPER, alias = "any solid copper block" ) - fun copperGrate() = type(Material.COPPER_GRATE) - fun copperBulb() = type(Material.COPPER_BULB) + fun copperGrate() = anyType( + Material.COPPER_GRATE, + Material.EXPOSED_COPPER_GRATE, + Material.WEATHERED_COPPER_GRATE, + Material.OXIDIZED_COPPER_GRATE, + Material.WAXED_COPPER_GRATE, + Material.WAXED_EXPOSED_COPPER_GRATE, + Material.WAXED_WEATHERED_COPPER_GRATE, + Material.WAXED_OXIDIZED_COPPER_GRATE, + alias = "any copper bulb" + ) + fun copperBulb() = anyType( + Material.COPPER_BULB, + Material.EXPOSED_COPPER_BULB, + Material.WEATHERED_COPPER_BULB, + Material.OXIDIZED_COPPER_BULB, + Material.WAXED_COPPER_BULB, + Material.WAXED_EXPOSED_COPPER_BULB, + Material.WAXED_WEATHERED_COPPER_BULB, + Material.WAXED_OXIDIZED_COPPER_BULB, + alias = "any copper bulb" + ) fun fluidInput() = type(Material.FLETCHING_TABLE) fun titaniumBlock() = customBlock(CustomBlocks.TITANIUM_BLOCK) @@ -482,7 +508,12 @@ class MultiblockShape { fun machineFurnace() = complete(BlockRequirement( alias = "furnace", - example = Material.FURNACE.createBlockData(), + example = { direction -> + Material.FURNACE.createBlockData { + it as Furnace + it.facing = direction.oppositeFace + } + }, syncCheck = check@{ block, inward, loadChunks -> val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockSateSafe(block.world, block.x, block.y, block.z) ?: return@check false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt index 47c5d41a80..fc7f7e46b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt @@ -1,6 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.type.navigationcomputer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.LEFT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.RIGHT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.SELF +import org.bukkit.block.data.Bisected.Half.BOTTOM +import org.bukkit.block.data.Bisected.Half.TOP +import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT sealed class NavigationComputerMultiblockAdvanced : NavigationComputerMultiblock() { override val signText = createSignText( @@ -17,26 +24,26 @@ data object VerticalNavigationComputerMultiblockAdvanced : NavigationComputerMul override fun MultiblockShape.buildStructure() { z(+0) { y(+0) { - x(-2).anyStairs() - x(-1).anyStairs() + x(-2).anyStairs(PrepackagedPreset.stairs(SELF, TOP, shape = STRAIGHT)) + x(-1).anyStairs(PrepackagedPreset.stairs(SELF, TOP, shape = STRAIGHT)) x(+0).ironBlock() - x(+1).anyStairs() - x(+2).anyStairs() + x(+1).anyStairs(PrepackagedPreset.stairs(SELF, TOP, shape = STRAIGHT)) + x(+2).anyStairs(PrepackagedPreset.stairs(SELF, TOP, shape = STRAIGHT)) } y(+1) { x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlassPane() - x(+1).anyGlassPane() + x(-1).anyGlassPane(PrepackagedPreset.pane(LEFT, RIGHT)) + x(+0).anyGlassPane(PrepackagedPreset.pane(LEFT, RIGHT)) + x(+1).anyGlassPane(PrepackagedPreset.pane(LEFT, RIGHT)) x(+2).ironBlock() } y(+2) { - x(-2).anyStairs() - x(-1).anyStairs() + x(-2).anyStairs(PrepackagedPreset.stairs(SELF, BOTTOM, shape = STRAIGHT)) + x(-1).anyStairs(PrepackagedPreset.stairs(SELF, BOTTOM, shape = STRAIGHT)) x(+0).ironBlock() - x(+1).anyStairs() - x(+2).anyStairs() + x(+1).anyStairs(PrepackagedPreset.stairs(SELF, BOTTOM, shape = STRAIGHT)) + x(+2).anyStairs(PrepackagedPreset.stairs(SELF, BOTTOM, shape = STRAIGHT)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt new file mode 100644 index 0000000000..7315e05832 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.multiblock.util + +import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace +import org.bukkit.Material +import org.bukkit.block.data.Bisected +import org.bukkit.block.data.type.Fence +import org.bukkit.block.data.type.Stairs + +object PrepackagedPreset { + fun stairs(face: RelativeFace, half: Bisected.Half, shape: Stairs.Shape): BlockRequirement.() -> Unit = { + example = { multiblockDirection -> + Material.STONE_BRICK_STAIRS.createBlockData { stairs -> + stairs as Stairs + stairs.half = half + stairs.shape = shape + stairs.facing = face[multiblockDirection] + } + } + } + + fun pane(vararg face: RelativeFace): BlockRequirement.() -> Unit = { + example = { multiblockDirection -> + Material.GLASS_PANE.createBlockData { pane -> + pane as Fence + face.forEach { pane.setFace(it[multiblockDirection], true) } + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt new file mode 100644 index 0000000000..3e9b429462 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.miscellaneous.utils.coordinates + +import net.horizonsend.ion.server.miscellaneous.utils.leftFace +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import org.bukkit.block.BlockFace + +enum class RelativeFace { + SELF { + override fun get(face: BlockFace): BlockFace { + return face + } + }, + OPPOSITE { + override fun get(face: BlockFace): BlockFace { + return face.oppositeFace + } + }, + RIGHT { + override fun get(face: BlockFace): BlockFace { + return face.rightFace + } + }, + LEFT { + override fun get(face: BlockFace): BlockFace { + return face.leftFace + } + }; + + abstract operator fun get(face: BlockFace): BlockFace +} From b7d5c945750fbbab12157a4eae78c8cc48f4a8a7 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 13:57:18 -0500 Subject: [PATCH 124/500] configuration for another --- .../type/fluid/storage/FluidTankMedium.kt | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt index 8cfcc4dfba..b6c6faac38 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt @@ -1,16 +1,22 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.storage import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.OPPOSITE +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.SELF +import org.bukkit.block.data.Bisected.Half.BOTTOM +import org.bukkit.block.data.Bisected.Half.TOP +import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT object FluidTankMedium : FluidStorageMultiblock(75_000) { override fun MultiblockShape.buildStructure() { z(0) { y(-1) { - x(-2).anyStairs() + x(-2).anyStairs(stairs(SELF, TOP, shape = STRAIGHT)) x(-1).extractor() x(+0).fluidInput() x(+1).extractor() - x(+2).anyStairs() + x(+2).anyStairs(stairs(SELF, TOP, shape = STRAIGHT)) } y(+0) { x(-2).anyCopperVariant() @@ -20,11 +26,11 @@ object FluidTankMedium : FluidStorageMultiblock(75_000) { x(+2).anyCopperVariant() } y(+1) { - x(-2).anyStairs() + x(-2).anyStairs(stairs(SELF, BOTTOM, shape = STRAIGHT)) x(-1).titaniumBlock() x(+0).copperGrate() x(+1).titaniumBlock() - x(+2).anyStairs() + x(+2).anyStairs(stairs(SELF, BOTTOM, shape = STRAIGHT)) } } z(1) { @@ -52,11 +58,11 @@ object FluidTankMedium : FluidStorageMultiblock(75_000) { } z(2) { y(-1) { - x(-2).anyStairs() + x(-2).anyStairs(stairs(OPPOSITE, TOP, shape = STRAIGHT)) x(-1).titaniumBlock() x(+0).copperGrate() x(+1).titaniumBlock() - x(+2).anyStairs() + x(+2).anyStairs(stairs(OPPOSITE, TOP, shape = STRAIGHT)) } y(+0) { x(-2).anyCopperVariant() @@ -66,11 +72,11 @@ object FluidTankMedium : FluidStorageMultiblock(75_000) { x(+2).anyCopperVariant() } y(+1) { - x(-2).anyStairs() + x(-2).anyStairs(stairs(OPPOSITE, BOTTOM, shape = STRAIGHT)) x(-1).titaniumBlock() x(+0).anyCopperBlock() x(+1).titaniumBlock() - x(+2).anyStairs() + x(+2).anyStairs(stairs(OPPOSITE, BOTTOM, shape = STRAIGHT)) } } } From ca8aee6c943edf59bad45a3197527c60826e21ee Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 14:22:07 -0500 Subject: [PATCH 125/500] implement new gas collection system --- .../server/features/gas/collection/Factors.kt | 3 ++ .../collector/PipedGasCollectorMultiblock.kt | 37 ++++++++++++++++--- .../persistence/NamespacedKeys.kt | 4 ++ 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/collection/Factors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/collection/Factors.kt index a3f682707f..7763f7e6e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/collection/Factors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/collection/Factors.kt @@ -9,6 +9,9 @@ import kotlin.random.Random @Serializable sealed interface Factor { + /** + * A gas collection factor. It returns a value in liters per second. + **/ fun getAmount(location: Location): Int } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index e845dfd192..732206228a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -3,17 +3,21 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.collector import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.CategoryRestrictedInternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.StorageContainer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN -import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory.GAS +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GOLD @@ -23,6 +27,8 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import kotlin.math.abs +import kotlin.math.roundToInt object PipedGasCollectorMultiblock : Multiblock(), EntityMultiblock, @@ -95,14 +101,33 @@ object PipedGasCollectorMultiblock : Multiblock(), z: Int, world: World, structureDirection: BlockFace, - ) : BasicFluidStoringEntity(manager, PipedGasCollectorMultiblock, data, x, y, z, world, structureDirection, CategoryRestrictedInternalStorage(500, FluidCategory.GAS)), + ) : MultiblockEntity(manager, PipedGasCollectorMultiblock, x, y, z, world, structureDirection), AsyncTickingMultiblockEntity, FluidStoringEntity { + override val capacities: Array = arrayOf( + StorageContainer("tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), + StorageContainer("tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), + StorageContainer("tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), + ) + private var lastTicked: Long = System.currentTimeMillis() + private val worldConfig get() = world.ion.configuration.gasConfiguration + override suspend fun tickAsync() { - mainStorage.storage.addAmount(HYDROGEN, 1) + val amounts = worldConfig.gasses.associate { it.gas to it.factorStack.getAmount(location) } + + val time = System.currentTimeMillis() + + val deltaT = (time - lastTicked).toDouble() / 1000.0 + + amounts.forEach { (gas, amount) -> + val fluid = gas.fluid + firstCasStore(fluid, amount)?.storage?.addAmount(fluid, abs(amount * deltaT).roundToInt()) //TODO remove abs + } + + lastTicked = time } override fun onLoad() { @@ -118,7 +143,7 @@ object PipedGasCollectorMultiblock : Multiblock(), } override fun toString(): String { - return "Piped gas collector. Storage: $mainStorage" + return "Piped gas collector. Storages: ${capacities.toList()}" } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 44b927e7cc..b132a7b69f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -110,6 +110,10 @@ object NamespacedKeys { val STORAGES = key("storages") val MAIN_STORAGE = key("main_storage") + val TANK_1 = key("tank_1") + val TANK_2 = key("tank_2") + val TANK_3 = key("tank_3") + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs From c3e14ef56dde8f04c07fb3fbe87ac676b08989a8 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 16:58:37 -0500 Subject: [PATCH 126/500] fixes --- .../collector/PipedGasCollectorMultiblock.kt | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 732206228a..10c20dbf6d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -27,7 +27,6 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import kotlin.math.abs import kotlin.math.roundToInt object PipedGasCollectorMultiblock : Multiblock(), @@ -106,9 +105,9 @@ object PipedGasCollectorMultiblock : Multiblock(), FluidStoringEntity { override val capacities: Array = arrayOf( - StorageContainer("tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), - StorageContainer("tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), - StorageContainer("tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), + loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), + loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), + loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), ) private var lastTicked: Long = System.currentTimeMillis() @@ -124,22 +123,15 @@ object PipedGasCollectorMultiblock : Multiblock(), amounts.forEach { (gas, amount) -> val fluid = gas.fluid - firstCasStore(fluid, amount)?.storage?.addAmount(fluid, abs(amount * deltaT).roundToInt()) //TODO remove abs + firstCasStore(fluid, amount)?.storage?.addAmount(fluid, (amount * deltaT).roundToInt()) } lastTicked = time } - override fun onLoad() { - - } - - override fun onUnload() { - - } - - override fun handleRemoval() { - + override fun storeAdditionalData(store: PersistentMultiblockData) { + val rawStorage = store.getAdditionalDataRaw() + storeStorageData(rawStorage, rawStorage.adapterContext) } override fun toString(): String { From 91b1b5d1ee5c03717f3342647618385b25afe675 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 17:47:24 -0500 Subject: [PATCH 127/500] utilities --- .../entity/type/fluids/FluidStoringEntity.kt | 38 +++++++++++++++++++ .../collector/PipedGasCollectorMultiblock.kt | 4 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 5f875184de..01a7bd926c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -12,10 +12,48 @@ import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { val capacities: Array + /** + * Returns whether any of the internal storages can store the amount of the fluid provided + **/ fun canStore(fluid: PipedFluid, amount: Int) = capacities.any { it.storage.canStore(fluid, amount) } + /** + * Returns the first internal storage that can contain the amount of the fluid provided. + **/ fun firstCasStore(fluid: PipedFluid, amount: Int): StorageContainer? = capacities.firstOrNull { it.storage.canStore(fluid, amount) } + /** + * Adds the amount of the fluid to the first available internal storage + **/ + fun addFirstAvailable(fluid: PipedFluid, amount: Int): Int { + var remaining = amount + + for (container in capacities.filter { it.storage.getStoredFluid() == fluid || it.storage.getStoredFluid() == null }) { + val unfit = container.storage.addAmount(fluid, remaining) + remaining -= (remaining - unfit) + + if (remaining <= 0) break + } + + return remaining + } + + /** + * Removes the amount of the fluid to the first available internal storage + **/ + fun removeFirstAvailable(fluid: PipedFluid, amount: Int): Int { + var remaining = amount + + for (container in capacities.filter { it.storage.getStoredFluid() == fluid || it.storage.getStoredFluid() == null }) { + val unRemoved = container.storage.remove(fluid, remaining) + remaining -= (remaining - unRemoved) + + if (remaining <= 0) break + } + + return remaining + } + fun getStoredResources() : Map = capacities.associate { it.storage.getStoredFluid() to it.storage.getAmount() } fun getNamedStorage(name: String): StorageContainer = capacities.first { it.name == name } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 10c20dbf6d..2e11ae3655 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -123,7 +123,9 @@ object PipedGasCollectorMultiblock : Multiblock(), amounts.forEach { (gas, amount) -> val fluid = gas.fluid - firstCasStore(fluid, amount)?.storage?.addAmount(fluid, (amount * deltaT).roundToInt()) + val adjusted = (amount * deltaT).roundToInt() + + addFirstAvailable(fluid, adjusted) } lastTicked = time From ee67dc7bb6da659b8a38e4b08a16b555e0e35a6a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 23:04:27 -0500 Subject: [PATCH 128/500] register water, electrolysis multi structure --- .../type/fluids/BasicFluidStoringEntity.kt | 2 + .../entity/type/fluids/FluidStoringEntity.kt | 4 +- .../entity/type/fluids/SingleFluidStorage.kt | 6 - .../CategoryRestrictedInternalStorage.kt | 2 +- .../fluids/{ => storage}/InternalStorage.kt | 2 +- .../type/fluids/storage/SingleFluidStorage.kt | 14 ++ .../fluids/{ => storage}/StorageContainer.kt | 2 +- .../{ => storage}/UnlimitedInternalStorage.kt | 2 +- .../newer/MultiblockRegistration.kt | 2 + .../multiblock/shape/MultiblockShape.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 186 ++++++++++++++++++ .../collector/PipedGasCollectorMultiblock.kt | 23 ++- .../fluid/storage/FluidStorageMultiblock.kt | 2 +- .../type/fluid/storage/FluidTankMedium.kt | 4 +- .../transport/fluids/TransportedFluids.kt | 1 + 15 files changed, 230 insertions(+), 24 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/{ => storage}/CategoryRestrictedInternalStorage.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/{ => storage}/InternalStorage.kt (99%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/{ => storage}/StorageContainer.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/{ => storage}/UnlimitedInternalStorage.kt (97%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index 0e560524a6..8ea7ef8daa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -3,6 +3,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 01a7bd926c..621bb56dce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES import net.kyori.adventure.text.Component @@ -44,7 +46,7 @@ interface FluidStoringEntity { fun removeFirstAvailable(fluid: PipedFluid, amount: Int): Int { var remaining = amount - for (container in capacities.filter { it.storage.getStoredFluid() == fluid || it.storage.getStoredFluid() == null }) { + for (container in capacities.filter { it.storage.getStoredFluid() == fluid }) { val unRemoved = container.storage.remove(fluid, remaining) remaining -= (remaining - unRemoved) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt deleted file mode 100644 index 80fc235662..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/SingleFluidStorage.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.fluids - -import org.bukkit.Fluid - -class SingleFluidStorage(private val fluid: Fluid, private val storageCapacity: Int) { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt index 341265a4c2..c3f0ebdd18 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/CategoryRestrictedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.fluids +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt index 9e60843f6b..6273bdc344 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.fluids +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt new file mode 100644 index 0000000000..04fb092532 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +class SingleFluidStorage(private val storageCapacity: Int, private val restrictedFluid: PipedFluid) : InternalStorage() { + override fun getCapacity(): Int = storageCapacity + + override fun canStore(resource: PipedFluid, liters: Int): Boolean { + if (liters + getAmount() > getCapacity()) return false + + // Check that the fluid attempting to be stored is the same as the one currently stored + return (getStoredFluid() == null || resource == restrictedFluid) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt index 9375a71f69..cfb9faa5b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/StorageContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.fluids +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.kyori.adventure.text.Component import org.bukkit.NamespacedKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt index 8826a3946a..7d38a67129 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/UnlimitedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.fluids +package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.horizonsend.ion.server.features.transport.fluids.PipedFluid diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt index 90892c340d..60e8cb2c2e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruis import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall @@ -113,6 +114,7 @@ object MultiblockRegistration : IonServerComponent() { // Gas registerMultiblock(PipedGasCollectorMultiblock) + registerMultiblock(ElectrolysisMultiblock) registerMultiblock(FluidTankSmall) registerMultiblock(FluidTankMedium) // registerMultiblock(FluidTankLarge) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 8907127c1d..5d7b395fd0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -422,7 +422,7 @@ class MultiblockShape { Material.WAXED_OXIDIZED_CUT_COPPER, alias = "any copper variant", ) - fun anyCopperBlock() = anyType( + fun copperBlock() = anyType( Material.COPPER_BLOCK, Material.EXPOSED_COPPER, Material.WEATHERED_COPPER, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt new file mode 100644 index 0000000000..b5f4ef8685 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -0,0 +1,186 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid + +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.SingleFluidStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane +import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs +import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.LEFT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.OPPOSITE +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.RIGHT +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.SELF +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.block.data.Bisected.Half.BOTTOM +import org.bukkit.block.data.Bisected.Half.TOP +import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent + +object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { + override val name: String = "Electrolysis" + + override val signText: Array = arrayOf( + text("Electrolysis", NamedTextColor.GOLD), + text("Machine", NamedTextColor.RED), + null, + null + ) + + override fun MultiblockShape.buildStructure() { + z(0) { + y(-1) { + x(-2).anyStairs(stairs(SELF, TOP, STRAIGHT)) + x(-1).craftingTable() + x(+0).fluidInput() + x(+1).craftingTable() + x(+2).anyStairs(stairs(SELF, TOP, STRAIGHT)) + } + y(+0) { + x(-2).anyStairs(stairs(SELF, BOTTOM, STRAIGHT)) + x(-1).anyGlass() + x(+0).copperBlock() + x(+1).anyGlass() + x(+2).anyStairs(stairs(SELF, BOTTOM, STRAIGHT)) + } + y(+1) { + x(-2).anyGlassPane(pane(SELF, RIGHT)) + x(-1).anyGlass() + x(+0).anyGlassPane(pane(LEFT, RIGHT)) + x(+1).anyGlass() + x(+2).anyGlassPane(pane(SELF, LEFT)) + } + y(+2) { + x(-2).anyGlassPane(pane(SELF, RIGHT)) + x(-1).anyGlass() + x(+0).anyGlassPane(pane(LEFT, RIGHT)) + x(+1).anyGlass() + x(+2).anyGlassPane(pane(SELF, LEFT)) + } + } + z(1) { + y(-1) { + x(-2).titaniumBlock() + x(-1).redstoneBlock() + x(+0).copperBlock() + x(+1).redstoneBlock() + x(+2).titaniumBlock() + } + y(+0) { + x(-2).titaniumBlock() + x(-1).copperGrate() + x(+0).copperBlock() + x(+1).copperGrate() + x(+2).titaniumBlock() + } + y(+1) { + x(-2).anyGlass() + x(-1).copperGrate() + x(+0).anyGlass() + x(+1).copperGrate() + x(+2).anyGlass() + } + y(+2) { + x(-2).anyGlass() + x(-1).copperGrate() + x(+0).anyGlass() + x(+1).copperGrate() + x(+2).anyGlass() + } + } + z(2) { + y(-1) { + x(-2).anyStairs(stairs(OPPOSITE, TOP, STRAIGHT)) + x(-1).titaniumBlock() + x(+0).copperBlock() + x(+1).titaniumBlock() + x(+2).anyStairs(stairs(OPPOSITE, TOP, STRAIGHT)) + } + y(+0) { + x(-2).anyStairs(stairs(OPPOSITE, BOTTOM, STRAIGHT)) + x(-1).titaniumBlock() + x(+0).anyStairs(stairs(OPPOSITE, BOTTOM, STRAIGHT)) + x(+1).titaniumBlock() + x(+2).anyStairs(stairs(OPPOSITE, BOTTOM, STRAIGHT)) + } + y(+1) { + x(-2).anyGlassPane(pane(OPPOSITE, RIGHT)) + x(-1).anyGlass() + x(+0).anyGlassPane(pane(LEFT, RIGHT)) + x(+1).anyGlass() + x(+2).anyGlassPane(pane(OPPOSITE, LEFT)) + } + y(+2) { + x(-2).anyGlassPane(pane(OPPOSITE, RIGHT)) + x(-1).anyGlass() + x(+0).anyGlassPane(pane(LEFT, RIGHT)) + x(+1).anyGlass() + x(+2).anyGlassPane(pane(OPPOSITE, LEFT)) + } + } + } + + override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): ElectrolysisMultiblockEntity { + return ElectrolysisMultiblockEntity(manager, data, x, y, z, world, structureDirection) + } + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val entity = getMultiblockEntity(sign) + + player.information(entity.toString()) + } + + class ElectrolysisMultiblockEntity( + manager: ChunkMultiblockManager, + data: PersistentMultiblockData, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : MultiblockEntity( + manager, + ElectrolysisMultiblock, + x, + y, + z, + world, + structureDirection + ), AsyncTickingMultiblockEntity, FluidStoringEntity { + override val capacities: Array = arrayOf( + loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_1, SingleFluidStorage(500, HYDROGEN)), + loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(500, OXYGEN)), + loadStoredResource(data, "water_tank", text("Water Tank"), TANK_3, SingleFluidStorage(500, WATER)) + ) + + override suspend fun tickAsync() { + + } + + override fun toString(): String = """ + Electrolysis multi + Hydrogen: ${getNamedStorage("hydrogen_tank")} + Oxygen: ${getNamedStorage("oxygen_tank")} + Water: ${getNamedStorage("water_tank")} + """.trimIndent() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 2e11ae3655..95ac33949c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -6,9 +6,9 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.CategoryRestrictedInternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.StorageContainer +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.CategoryRestrictedInternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock @@ -45,7 +45,7 @@ object PipedGasCollectorMultiblock : Multiblock(), z(0) { y(0) { x(-1).lightningRod() - x(0).anyCopperBlock() + x(0).copperBlock() x(+1).lightningRod() } y(-1) { @@ -70,12 +70,12 @@ object PipedGasCollectorMultiblock : Multiblock(), z(+2) { y(0) { x(-1).lightningRod() - x(0).anyCopperBlock() + x(0).copperBlock() x(+1).lightningRod() } y(-1) { x(-1).anyStairs() - x(0).anyCopperBlock() + x(0).copperBlock() x(+1).anyStairs() } @@ -100,10 +100,15 @@ object PipedGasCollectorMultiblock : Multiblock(), z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, PipedGasCollectorMultiblock, x, y, z, world, structureDirection), - AsyncTickingMultiblockEntity, - FluidStoringEntity - { + ) : MultiblockEntity( + manager, + PipedGasCollectorMultiblock, + x, + y, + z, + world, + structureDirection + ), AsyncTickingMultiblockEntity, FluidStoringEntity { override val capacities: Array = arrayOf( loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 3d404735ce..8d36264974 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.UnlimitedInternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.UnlimitedInternalStorage import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt index b6c6faac38..ebfb5020c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidTankMedium.kt @@ -37,7 +37,7 @@ object FluidTankMedium : FluidStorageMultiblock(75_000) { y(-1) { x(-2).anyCopperVariant() x(-1).titaniumBlock() - x(+0).anyCopperBlock() + x(+0).copperBlock() x(+1).titaniumBlock() x(+2).anyCopperVariant() } @@ -74,7 +74,7 @@ object FluidTankMedium : FluidStorageMultiblock(75_000) { y(+1) { x(-2).anyStairs(stairs(OPPOSITE, BOTTOM, shape = STRAIGHT)) x(-1).titaniumBlock() - x(+0).anyCopperBlock() + x(+0).copperBlock() x(+1).titaniumBlock() x(+2).anyStairs(stairs(OPPOSITE, BOTTOM, shape = STRAIGHT)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt index 74844883fe..b0e51d1676 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt @@ -18,6 +18,7 @@ object TransportedFluids : IonServerComponent() { val FLUORINE = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) val HELIUM = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) val CARBON_DIOXIDE = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) + val WATER = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) init { pipedFluids.associateByTo(byIdentifier) { it.identifier } From 77c39eb5628c750684a9e528f3e209d9399c1b05 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 23:26:08 -0500 Subject: [PATCH 129/500] basic electrolysis functionality --- .../type/fluids/BasicFluidStoringEntity.kt | 2 +- .../entity/type/fluids/FluidStoringEntity.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 34 +++++++++++++++---- .../collector/PipedGasCollectorMultiblock.kt | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index 8ea7ef8daa..87ffcaf134 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -34,6 +34,6 @@ abstract class BasicFluidStoringEntity( override fun storeAdditionalData(store: PersistentMultiblockData) { val rawStorage = store.getAdditionalDataRaw() - storeStorageData(rawStorage, rawStorage.adapterContext) + storeFluidData(rawStorage, rawStorage.adapterContext) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 621bb56dce..d29579389f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -63,7 +63,7 @@ interface FluidStoringEntity { fun getStorage(key: NamespacedKey): StorageContainer = capacities.first { it.namespacedKey == key } - fun storeStorageData(destination: PersistentDataContainer, context: PersistentDataAdapterContext) { + fun storeFluidData(destination: PersistentDataContainer, context: PersistentDataAdapterContext) { val storages = context.newPersistentDataContainer() capacities.forEach { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index b5f4ef8685..ab1224f5b5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -37,7 +37,8 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { - override val name: String = "Electrolysis" + override val name: String = "ElectrolysisMultiblock" + override val alternativeDetectionNames: Array = arrayOf("Electrolysis") override val signText: Array = arrayOf( text("Electrolysis", NamedTextColor.GOLD), @@ -146,6 +147,8 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf( - loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_1, SingleFluidStorage(500, HYDROGEN)), - loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(500, OXYGEN)), - loadStoredResource(data, "water_tank", text("Water Tank"), TANK_3, SingleFluidStorage(500, WATER)) + loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER)), + loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN)), + loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN)) ) + private val hydrogenStorage by lazy {getNamedStorage("hydrogen_tank") } + private val oxygenStorage by lazy {getNamedStorage("oxygen_tank") } + private val waterStorage by lazy {getNamedStorage("water_tank") } + override suspend fun tickAsync() { + val remainder = waterStorage.storage.remove(WATER_INCREMENT) + val removed = WATER_INCREMENT - remainder + + oxygenStorage.storage.addAmount(3 * removed) + hydrogenStorage.storage.addAmount(6 * removed) + } + override fun storeAdditionalData(store: PersistentMultiblockData) { + val rawStorage = store.getAdditionalDataRaw() + storeFluidData(rawStorage, rawStorage.adapterContext) } override fun toString(): String = """ Electrolysis multi - Hydrogen: ${getNamedStorage("hydrogen_tank")} - Oxygen: ${getNamedStorage("oxygen_tank")} - Water: ${getNamedStorage("water_tank")} + Hydrogen: $hydrogenStorage + Oxygen: $oxygenStorage + Water: $waterStorage """.trimIndent() + + companion object { + const val WATER_INCREMENT = 5 + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 95ac33949c..4226b54729 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -138,7 +138,7 @@ object PipedGasCollectorMultiblock : Multiblock(), override fun storeAdditionalData(store: PersistentMultiblockData) { val rawStorage = store.getAdditionalDataRaw() - storeStorageData(rawStorage, rawStorage.adapterContext) + storeFluidData(rawStorage, rawStorage.adapterContext) } override fun toString(): String { From b553bb4b2cf3506d8330e33244dbc209ffa2151d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 31 Aug 2024 23:51:37 -0500 Subject: [PATCH 130/500] setfluid command --- .../ion/server/command/qol/SetFluidCommand.kt | 63 +++++++++++++++++++ .../type/fluid/ElectrolysisMultiblock.kt | 2 - .../transport/fluids/TransportedFluids.kt | 4 +- .../miscellaneous/registrations/Commands.kt | 2 + 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt new file mode 100644 index 0000000000..d5e4a109b0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt @@ -0,0 +1,63 @@ +package net.horizonsend.ion.server.command.qol + +import co.aikar.commands.InvalidCommandArgument +import co.aikar.commands.PaperCommandManager +import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.CommandCompletion +import co.aikar.commands.annotation.CommandPermission +import co.aikar.commands.annotation.Default +import net.horizonsend.ion.common.extensions.success +import net.horizonsend.ion.server.command.SLCommand +import net.horizonsend.ion.server.command.admin.debug +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.miscellaneous.utils.getSelection +import org.bukkit.entity.Player + +@CommandAlias("setfluid") +@CommandPermission("ion.setfluid") +object SetFluidCommand : SLCommand() { + override fun onEnable(manager: PaperCommandManager) { + manager.commandCompletions.registerCompletion("fluids") { + TransportedFluids.getAll().map { it.identifier } + } + + manager.commandContexts.registerContext(PipedFluid::class.java) { + val id = it.popFirstArg() + TransportedFluids[id] ?: throw InvalidCommandArgument("Fluid $id not found!") + } + + manager.commandCompletions.setDefaultCompletion("fluids", PipedFluid::class.java) + } + + @Default + @CommandCompletion("0|1000|500000|2147483647 true|false") + @Suppress("unused") + fun onSetFluid(sender: Player, fluid: PipedFluid, amount: Int, storeName: String) { + val selection = runCatching { sender.getSelection() }.getOrNull() ?: fail { "You must make a selection!" } + + if (sender.world.name != selection.world?.name) return + + var hits = 0 + + for (blockPosition in selection) { + val x = blockPosition.x + val y = blockPosition.y + val z = blockPosition.z + + sender.debug("checking block at $x $y $z") + + val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) + if (entity !is FluidStoringEntity) continue + + entity.getNamedStorage(storeName).storage.setContents(fluid, amount) + hits++ + + sender.debug("power sent") + } + + sender.success("Set $hits multiblocks' $storeName's ${fluid.identifier} to $amount.") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index ab1224f5b5..c7f920eecf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -147,8 +147,6 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = listOf( CheckProtectionCommand, FixExtractorsCommand, SetPowerCommand, + SetFluidCommand, RegenerateCommand, RemoveGhostShipCommand, From f9cefc4602c2a727ed2cc7d7c1f733b7a4c0bc66 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Sep 2024 00:17:42 -0500 Subject: [PATCH 131/500] rename gas network to fluid, build out some code --- .../{GasNetwork.kt => FluidNetwork.kt} | 12 +++--- .../features/transport/node/NodeType.kt | 2 +- .../features/transport/node/NodeUtils.kt | 2 +- ...ExtractorNode.kt => FluidExtractorNode.kt} | 2 +- ...{GasNodeFactory.kt => FluidNodeFactory.kt} | 38 ++++++++++++++++-- .../transport/node/gas/GasJunctionNode.kt | 6 +-- .../transport/node/gas/LightningRodNode.kt | 6 +-- .../step/origin/gas/ExtractedGasOrigin.kt | 8 ++-- .../server/miscellaneous/utils/Materials.kt | 39 +++++++++++++++++++ 9 files changed, 92 insertions(+), 23 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/{GasNetwork.kt => FluidNetwork.kt} (60%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/{GasExtractorNode.kt => FluidExtractorNode.kt} (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/{GasNodeFactory.kt => FluidNodeFactory.kt} (66%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/GasNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/FluidNetwork.kt similarity index 60% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/GasNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/FluidNetwork.kt index 54b7314902..890491c16c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/GasNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/FluidNetwork.kt @@ -2,19 +2,19 @@ package net.horizonsend.ion.server.features.transport.network import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.gas.GasExtractorNode -import net.horizonsend.ion.server.features.transport.node.gas.GasNodeFactory +import net.horizonsend.ion.server.features.transport.node.gas.FluidExtractorNode +import net.horizonsend.ion.server.features.transport.node.gas.FluidNodeFactory import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.GAS_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap -class GasNetwork(holder: NetworkHolder) : TransportNetwork(holder) { +class FluidNetwork(holder: NetworkHolder) : TransportNetwork(holder) { override val namespacedKey: NamespacedKey = GAS_TRANSPORT - override val type: NetworkType = NetworkType.GAS - override val nodeFactory = GasNodeFactory(this) + override val type: NetworkType = NetworkType.FLUID + override val nodeFactory = FluidNodeFactory(this) - val extractors: ConcurrentHashMap = ConcurrentHashMap() + val extractors: ConcurrentHashMap = ConcurrentHashMap() override val dataVersion: Int = 0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 5826982fa3..f23636500b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -24,7 +24,7 @@ enum class NodeType(val clazz: Class) { POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), - //GAS + //FLUID //ITEM ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index 8d0586eb40..1ab30acfd2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -68,7 +68,7 @@ enum class NetworkType { TODO("Not yet implemented") } }, - GAS { + FLUID { override fun get(chunk: IonChunk): TransportNetwork { return chunk.transportNetwork.powerNetwork.network } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt index eea5cb75f0..b3b2f28213 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.gas -class GasExtractorNode { +class FluidExtractorNode { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidNodeFactory.kt similarity index 66% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidNodeFactory.kt index 03bbdab48f..bd9ba1a969 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidNodeFactory.kt @@ -1,7 +1,8 @@ package net.horizonsend.ion.server.features.transport.node.gas +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.GasNetwork +import net.horizonsend.ion.server.features.transport.network.FluidNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.handleMerges @@ -9,18 +10,47 @@ import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.faces +import net.horizonsend.ion.server.miscellaneous.utils.isChiseledCopper +import net.horizonsend.ion.server.miscellaneous.utils.isCopperBlock +import net.horizonsend.ion.server.miscellaneous.utils.isCopperBulb +import org.bukkit.Material import org.bukkit.block.data.Directional -class GasNodeFactory(network: GasNetwork) : NodeFactory(network) { +class FluidNodeFactory(network: FluidNetwork) : NodeFactory(network) { override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { if (network.nodes.contains(key)) return when { // Straight wires -// snapshot.type == Material.END_ROD -> addLightningRod(snapshot.data as Directional, key) + snapshot.type == Material.LIGHTNING_ROD -> addLightningRod(snapshot.data as Directional, key) // Omnidirectional wires -// snapshot.type == Material.SPONGE -> addJunction(key) + snapshot.type.isCopperBlock -> addJunction(key) + + // Extractor + snapshot.type == Material.CRAFTING_TABLE -> println("TODO") + + // Input + snapshot.type == Material.FLETCHING_TABLE -> println("TODO") + + // Flow meter + snapshot.type == Material.OBSERVER -> println("TODO") + + // Merge + snapshot.type == Material.REDSTONE_BLOCK -> println("TODO") + snapshot.type == Material.IRON_BLOCK -> println("TODO") + + // Inverted Merge + snapshot.type == Material.LAPIS_BLOCK -> println("TODO") + + // Splitter + CustomBlocks.getByBlockData(snapshot.data) == CustomBlocks.ALUMINUM_BLOCK -> println("TODO") + + // Valve + snapshot.type.isChiseledCopper -> println("TODO") + + // Filter + snapshot.type.isCopperBulb -> println("TODO") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt index 56cc30965a..f70c6b7f76 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.node.gas -import net.horizonsend.ion.server.features.transport.network.GasNetwork +import net.horizonsend.ion.server.features.transport.network.FluidNetwork import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -class GasJunctionNode(network: GasNetwork) : JunctionNode(network) { - constructor(network: GasNetwork, origin: BlockKey) : this(network) { +class GasJunctionNode(network: FluidNetwork) : JunctionNode(network) { + constructor(network: FluidNetwork, origin: BlockKey) : this(network) { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt index 890dd61b2f..73cffb2ab2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt @@ -1,14 +1,14 @@ package net.horizonsend.ion.server.features.transport.node.gas import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.GasNetwork +import net.horizonsend.ion.server.features.transport.network.FluidNetwork import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.block.data.Directional -class LightningRodNode(network: GasNetwork) : LinearNode(network) { - constructor(network: GasNetwork, origin: Long, axis: Axis) : this(network) { +class LightningRodNode(network: FluidNetwork) : LinearNode(network) { + constructor(network: FluidNetwork, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt index 0c46763489..1c1e348444 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport.step.origin.gas -import net.horizonsend.ion.server.features.transport.network.GasNetwork -import net.horizonsend.ion.server.features.transport.node.gas.GasExtractorNode +import net.horizonsend.ion.server.features.transport.network.FluidNetwork +import net.horizonsend.ion.server.features.transport.node.gas.FluidExtractorNode import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin class ExtractedGasOrigin( - val extractorNode: GasExtractorNode -) : StepOrigin + val extractorNode: FluidExtractorNode +) : StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt index 93a1b04c91..bb140164ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt @@ -127,3 +127,42 @@ val Material.isTankPassable: Boolean get() = TANK_PASSABLE_TYPES.contains(this) // Bisected is double plants val TANK_PASSABLE_TYPES = getMatchingMaterials { it.isAir || it.data == Bisected::class.java } + +val COPPER_BLOCK_TYPES = enumSetOf( + Material.COPPER_BLOCK, + Material.EXPOSED_COPPER, + Material.WEATHERED_COPPER, + Material.OXIDIZED_COPPER, + Material.WAXED_COPPER_BLOCK, + Material.WAXED_EXPOSED_COPPER, + Material.WAXED_WEATHERED_COPPER, + Material.WAXED_OXIDIZED_COPPER +) + +val Material.isCopperBlock get() = COPPER_BLOCK_TYPES.contains(this) + +val COPPER_BULB_TYPES = enumSetOf( + Material.COPPER_BULB, + Material.EXPOSED_COPPER_BULB, + Material.WEATHERED_COPPER_BULB, + Material.OXIDIZED_COPPER_BULB, + Material.WAXED_COPPER_BULB, + Material.WAXED_EXPOSED_COPPER_BULB, + Material.WAXED_WEATHERED_COPPER_BULB, + Material.WAXED_OXIDIZED_COPPER_BULB +) + +val Material.isCopperBulb get() = COPPER_BULB_TYPES.contains(this) + +val CHISELED_COPPER_TYPES = enumSetOf( + Material.CHISELED_COPPER, + Material.EXPOSED_CHISELED_COPPER, + Material.WEATHERED_CHISELED_COPPER, + Material.OXIDIZED_CHISELED_COPPER, + Material.WAXED_CHISELED_COPPER, + Material.WAXED_EXPOSED_CHISELED_COPPER, + Material.WAXED_WEATHERED_CHISELED_COPPER, + Material.WAXED_OXIDIZED_CHISELED_COPPER +) + +val Material.isChiseledCopper get() = CHISELED_COPPER_TYPES.contains(this) From 2bdc944c6974d6fa5b86d7b6c43c0232a94acc60 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 2 Sep 2024 00:10:23 -0500 Subject: [PATCH 132/500] add built in deltaT --- .../features/multiblock/entity/MultiblockEntity.kt | 11 +++++++++++ .../fluid/collector/PipedGasCollectorMultiblock.kt | 8 +------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 6ac485d4c2..05de3a1ff8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -37,6 +37,17 @@ abstract class MultiblockEntity( var structureDirection: BlockFace ): PDCSerializable { + private var lastRetrieved = System.currentTimeMillis() + + /** Gets the time since this value was last retrieved */ + protected val deltaTMS: Long get() { + val time = System.currentTimeMillis() + val delta = time - lastRetrieved + lastRetrieved = time + + return delta + } + /** Mark this entity as having been removed */ var removed: Boolean = false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 4226b54729..05025f13cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -115,16 +115,12 @@ object PipedGasCollectorMultiblock : Multiblock(), loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), ) - private var lastTicked: Long = System.currentTimeMillis() - private val worldConfig get() = world.ion.configuration.gasConfiguration override suspend fun tickAsync() { val amounts = worldConfig.gasses.associate { it.gas to it.factorStack.getAmount(location) } - val time = System.currentTimeMillis() - - val deltaT = (time - lastTicked).toDouble() / 1000.0 + val deltaT = deltaTMS / 1000.0 amounts.forEach { (gas, amount) -> val fluid = gas.fluid @@ -132,8 +128,6 @@ object PipedGasCollectorMultiblock : Multiblock(), addFirstAvailable(fluid, adjusted) } - - lastTicked = time } override fun storeAdditionalData(store: PersistentMultiblockData) { From ece1efd6e2e9ff0d48ba42e04a745337084182f9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 2 Sep 2024 13:29:41 -0500 Subject: [PATCH 133/500] dont send prompt if only one variant --- .../net/horizonsend/ion/server/command/misc/MultiblockCommand.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 448d752ac4..8d45c0e9bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -57,6 +57,7 @@ object MultiblockCommand : SLCommand() { if (possibleTiers.size == 1) { onCheck(player, possibleTiers.first(), sign.x, sign.y, sign.z) + return } val message = Component.text() From 05606c1369344a9d0a7afc7c6041e9d168d20ef0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 00:55:58 -0500 Subject: [PATCH 134/500] make new multiblock code the default, cleanup --- .../server/command/misc/MultiblockCommand.kt | 2 +- .../ion/server/command/qol/SetFluidCommand.kt | 2 +- .../ion/server/command/qol/SetPowerCommand.kt | 2 +- .../server/features/machine/PowerMachines.kt | 2 +- .../machine/decomposer/Decomposers.kt | 6 +-- .../{newer => }/MultiblockAccess.kt | 13 +++-- .../{newer => }/MultiblockDetectedEvent.kt | 2 +- .../{newer => }/MultiblockEntities.kt | 2 +- .../{newer => }/MultiblockRegistration.kt | 3 +- .../server/features/multiblock/PrePackaged.kt | 2 - .../entity/PersistentMultiblockData.kt | 2 +- .../multiblock/{ => old}/Multiblocks.kt | 8 ++- .../multiblock/type/NewPoweredMultiblock.kt | 45 ++++++++++++++++ .../multiblock/type/areashield/AreaShield.kt | 5 +- .../type/defense/AntiAirCannonMultiblock.kt | 6 +-- .../type/misc/DecomposerMultiblock.kt | 10 +++- .../type/power/storage/PowerBankMultiblock.kt | 6 +-- .../type/starshipweapon/EntityMultiblock.kt | 2 +- .../starshipweapon/turret/TurretMultiblock.kt | 2 +- .../world/ChunkMultiblockManager.kt | 6 +-- .../server/features/starship/Interdiction.kt | 2 +- .../starship/active/SubsystemDetector.kt | 4 +- .../ion/server/features/transport/Wires.kt | 2 +- .../multiblock/MultiblockEntityInitializer.kt | 4 +- .../server/listener/fixers/CancelListeners.kt | 19 +++++++ .../server/listener/misc/FurnaceListener.kt | 2 +- .../server/listener/misc/InteractListener.kt | 51 ------------------- .../miscellaneous/registrations/Components.kt | 3 +- .../miscellaneous/registrations/Listeners.kt | 4 +- 29 files changed, 115 insertions(+), 104 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newer => }/MultiblockAccess.kt (95%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newer => }/MultiblockDetectedEvent.kt (52%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newer => }/MultiblockEntities.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newer => }/MultiblockRegistration.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{ => old}/Multiblocks.kt (98%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 8d45c0e9bb..6d11d3a73f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -14,7 +14,7 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.displayBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration +import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt index d5e4a109b0..4dfd8a29f3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt @@ -9,8 +9,8 @@ import co.aikar.commands.annotation.Default import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.command.admin.debug +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids import net.horizonsend.ion.server.miscellaneous.utils.getSelection diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt index 1eaf7867b4..361e15a3b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt @@ -8,8 +8,8 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.command.admin.debug +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt index 852e2668cc..6756d052fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.machine import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt index d51734a14b..bede26c575 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.miscellaneous.utils.CHISELED_TYPES @@ -17,7 +16,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Location import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.EventHandler import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent import kotlin.math.max @@ -29,10 +27,8 @@ object Decomposers : IonServerComponent() { private const val BLOCKS_PER_SECOND = 1000 private val FRAME_MATERIAL = CHISELED_TYPES - @EventHandler fun onClick(event: PlayerInteractEvent) { val sign = event.clickedBlock?.state as? Sign ?: return - val multiblock = Multiblocks[sign] as? DecomposerMultiblock ?: return val signLoc = sign.location if (event.action == Action.RIGHT_CLICK_BLOCK) { @@ -76,7 +72,7 @@ object Decomposers : IonServerComponent() { up, forward, event.player.uniqueId, - multiblock + DecomposerMultiblock ) if (busySigns.containsKey(signLoc)) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index b3bef506a6..5b355ebbfa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -1,8 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.newer +package net.horizonsend.ion.server.features.multiblock import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError @@ -10,10 +13,9 @@ import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.common.utils.text.subStringBetween import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.command.misc.MultiblockCommand -import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.getMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.removeMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.getMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities.removeMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -43,6 +45,7 @@ import java.util.concurrent.TimeUnit import kotlin.jvm.optionals.getOrNull object MultiblockAccess : IonServerComponent() { + val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) private val multiblockCache: MutableMap, Optional>> = mutableMapOf() /** @@ -268,7 +271,7 @@ object MultiblockAccess : IonServerComponent() { event.player.success("Detected new ${result.name}") } - fun checkInteractable(sign: Sign, event: PlayerInteractEvent) { + private fun checkInteractable(sign: Sign, event: PlayerInteractEvent) { // Quick check val multiblockType = getFast(sign) if (multiblockType !is InteractableMultiblock) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockDetectedEvent.kt similarity index 52% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockDetectedEvent.kt index df481eb6ad..8069d9fee1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockDetectedEvent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockDetectedEvent.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newer +package net.horizonsend.ion.server.features.multiblock //class MultiblockDetectedEvent(): PlayerEvent, Cancellable { //} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index d181b33535..5fa57a0a0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newer +package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 60e8cb2c2e..ec0e7c86db 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newer/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -1,8 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.newer +package net.horizonsend.ion.server.features.multiblock import com.google.common.collect.Multimap import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 2c2bff18e5..5bfbaff016 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index 04e6209abd..5766ebc376 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration +import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ADDITIONAL_MULTIBLOCK_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_SIGN_OFFSET diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 7ddd7b5489..493b985c11 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -1,14 +1,13 @@ -package net.horizonsend.ion.server.features.multiblock +package net.horizonsend.ion.server.features.multiblock.old import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.command.misc.MultiblockCommand.setupCommand +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess.multiblockCoroutineScope import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Bottom import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Side import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Top @@ -91,7 +90,6 @@ import java.util.UUID object Multiblocks : IonServerComponent() { private val multiblocks: MutableMap = mutableMapOf() - val multiblockCoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) override fun onEnable() { initMultiblocks() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt new file mode 100644 index 0000000000..67f5bc1cd5 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt @@ -0,0 +1,45 @@ +package net.horizonsend.ion.server.features.multiblock.type + +import net.horizonsend.ion.server.features.gear.getPower +import net.horizonsend.ion.server.features.gear.setPower +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.listener.SLEventListener +import org.bukkit.block.Sign +import org.bukkit.event.EventHandler +import org.bukkit.event.player.PlayerInteractEvent + +interface NewPoweredMultiblock : EntityMultiblock { + val maxPower: Int + + fun handleBatteryInput(sign: Sign, entity: PoweredMultiblockEntity, event: PlayerInteractEvent) { + val item = event.item ?: return + + val power = getPower(item) + var powerToTransfer = power * item.amount + if (powerToTransfer == 0) return + + val machinePower = entity.getPower() + val maxMachinePower = entity.maxPower + if (maxMachinePower - machinePower < powerToTransfer) { + powerToTransfer = maxMachinePower - machinePower + } + + setPower(item, power - powerToTransfer / item.amount) + entity.addPower(powerToTransfer) + } + + companion object : SLEventListener() { + @EventHandler + fun onPlayerInteract(event: PlayerInteractEvent) { + val sign = event.clickedBlock?.state as? Sign ?: return + val multiblock = MultiblockAccess.getFast(sign) ?: return + if (multiblock !is NewPoweredMultiblock<*>) return + val entity = multiblock.getMultiblockEntity(sign) ?: return + + multiblock.handleBatteryInput(sign, entity as PoweredMultiblockEntity, event) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt index 0fd1ed36de..a94e33fc02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt @@ -9,8 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER @@ -27,7 +26,7 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataType.INTEGER import java.util.concurrent.TimeUnit -abstract class AreaShield(val radius: Int) : Multiblock(), PowerStoringMultiblock, InteractableMultiblock, EntityMultiblock { +abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { override fun onTransformSign(player: Player, sign: Sign) { player.success("Area Shield created.") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt index 172fe4d83c..94dd8bc281 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.machine.AntiAirCannons import net.horizonsend.ion.server.features.machine.AntiAirCannons.isOccupied import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock @@ -75,8 +75,6 @@ object AntiAirCannonBaseMultiblock : Multiblock(), PowerStoringMultiblock, Inter override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { if (!PlayerStarshipControl.isHoldingController(player)) return - if (Multiblocks[sign] !is AntiAirCannonBaseMultiblock) return - val turretFacing = turretIntact(sign) ?: return player.userError("Turret not intact!") // this is just to insert them into the cooldown to prevent accidentally shooting right when boardingm @@ -666,7 +664,7 @@ object AntiAirCannonTurretMultiblock: RotatingMultiblock() { val originBlock = world.getBlockAt(x, y, z) val sign = originBlock.state as? Sign ?: continue - if (Multiblocks[sign] === AntiAirCannonBaseMultiblock) return sign + if (MultiblockAccess.getMultiblock(sign, checkStructure = true, loadChunks = false) === AntiAirCannonBaseMultiblock) return sign } return null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt index 4646119efd..c94ca7428a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt @@ -1,14 +1,18 @@ package net.horizonsend.ion.server.features.multiblock.type.misc +import net.horizonsend.ion.server.features.machine.decomposer.Decomposers import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder -object DecomposerMultiblock : Multiblock(), PowerStoringMultiblock { +object DecomposerMultiblock : Multiblock(), PowerStoringMultiblock, InteractableMultiblock { override val maxPower: Int = 75_000 override val name: String = "decomposer" override val signText = createSignText( @@ -26,4 +30,8 @@ object DecomposerMultiblock : Multiblock(), PowerStoringMultiblock { fun getStorage(sign: Sign): Inventory { return (sign.block.getRelative(BlockFace.DOWN).state as InventoryHolder).inventory } + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + Decomposers.onClick(event) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index fdc7bf4c0e..7a3794bcc0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material @@ -15,12 +15,10 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataType -abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { abstract val tierMaterial: Material override val name = "powerbank" - abstract val maxPower: Int - override val signText = createSignText( line1 = "&2Power &8Bank", line2 = "&4------", diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt index 66bc930a94..e8d7cec3e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt index 1f3e4791bf..2a3b3f898c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt @@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt index 9353ba7952..571708a56f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.world import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity @@ -62,7 +62,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { } for ((key, asyncTicking) in asyncTickingMultiblockEntities) runCatching { - Multiblocks.multiblockCoroutineScope.launch { asyncTicking.tickAsync() } + MultiblockAccess.multiblockCoroutineScope.launch { asyncTicking.tickAsync() } }.onFailure { e -> log.warn("Exception ticking async multiblock ${asyncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") e.printStackTrace() @@ -120,7 +120,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { /** * Save the multiblock data back into the chunk **/ - private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = Multiblocks.multiblockCoroutineScope.launch { + private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = MultiblockAccess.multiblockCoroutineScope.launch { val old = chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) old?.let { chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY, it) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt index 439ea2a621..8b02de5ed1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.CHETHERITE -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index c6c76f32a4..49110c3a47 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.common.database.schema.Cryopod import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock @@ -13,8 +13,8 @@ import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultibloc import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt index 68f73ad3a3..e8d7ee0fb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt @@ -5,7 +5,7 @@ import com.google.common.cache.CacheLoader import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.debugHighlightBlock import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt index 6ad613f77a..c578cffb6d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.world.data.fixers.multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.data.SignDataFixer import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt index 1fe5defd46..4e381d90a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt @@ -2,18 +2,21 @@ package net.horizonsend.ion.server.listener.fixers import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent import io.papermc.paper.event.player.PlayerOpenSignEvent +import net.horizonsend.ion.common.extensions.successActionMessage import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.enumSetOf +import net.horizonsend.ion.server.miscellaneous.utils.isBed import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.minecraft.world.entity.item.ItemEntity import org.bukkit.Material import org.bukkit.entity.EnderPearl import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority +import org.bukkit.event.block.Action import org.bukkit.event.block.BlockDispenseEvent import org.bukkit.event.block.BlockExplodeEvent import org.bukkit.event.block.BlockFadeEvent @@ -25,6 +28,7 @@ import org.bukkit.event.entity.EntityExplodeEvent import org.bukkit.event.entity.PotionSplashEvent import org.bukkit.event.inventory.PrepareItemCraftEvent import org.bukkit.event.player.PlayerFishEvent +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.player.PlayerItemConsumeEvent import org.bukkit.event.player.PlayerKickEvent import org.bukkit.event.player.PlayerTeleportEvent @@ -198,4 +202,19 @@ class CancelListeners : SLEventListener() { event.isCancelled = true } } + + // Disable beds + @EventHandler + fun onPlayerInteractEventH(event: PlayerInteractEvent) { + if (event.action != Action.RIGHT_CLICK_BLOCK) return + val item = event.clickedBlock!! + val player = event.player + + if (item.type.isBed) { + event.isCancelled = true + player.successActionMessage( + "Beds are disabled on this server! Use a cryopod instead" + ) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt index 871f5da14c..6fc3bb98d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt @@ -33,7 +33,7 @@ object FurnaceListener : SLEventListener() { val sign = signBlock.getState(false) as Sign val checkStructure = false val loadChunks = false - val multiblock = Multiblocks[sign, checkStructure, loadChunks] + val multiblock = MultiblockAccess.getMultiblock(sign, checkStructure, loadChunks) if (multiblock is FurnaceMultiblock) { if (Multiblocks[sign, true, false] !== multiblock) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt deleted file mode 100644 index 8b69ca0745..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/InteractListener.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.horizonsend.ion.server.listener.misc - -import net.horizonsend.ion.common.extensions.successActionMessage -import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.utils.isBed -import org.bukkit.block.Sign -import org.bukkit.event.EventHandler -import org.bukkit.event.block.Action -import org.bukkit.event.player.PlayerInteractEvent - -object InteractListener : SLEventListener() { - // Put power into the sign if right clicking with a battery - - /* - // When not in creative mode, make breaking a custom item drop the proper drops - @EventHandler(priority = EventPriority.MONITOR) - fun onBlockBreakEvent(event: BlockBreakEvent) { - if (event.isCancelled) return - if (event.player.gameMode == GameMode.CREATIVE) return - - val block = event.block - val customBlock = CustomBlocks[block] ?: return - - if (event.isDropItems) { - event.isDropItems = false - block.type = Material.AIR - } - - val itemUsed = event.player.inventory.itemInMainHand - val location = block.location.toCenterLocation() - Tasks.sync { - for (drop in customBlock.getDrops(itemUsed)) { - block.world.dropItem(location, drop) - } - } - } - */ - - // Disable beds - @EventHandler - fun onPlayerInteractEventH(event: PlayerInteractEvent) { - if (event.action != Action.RIGHT_CLICK_BLOCK) return - val item = event.clickedBlock!! - val player = event.player - - if (item.type.isBed) { - event.isCancelled = true - player.successActionMessage("Beds are disabled on this server! Use a cryopod instead") - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 403c45dfea..1ee24f603c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -37,7 +37,8 @@ import net.horizonsend.ion.server.features.misc.GameplayTweaks import net.horizonsend.ion.server.features.misc.ProxyMessaging import net.horizonsend.ion.server.features.misc.Shuttles import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 0842cf719e..6854f08727 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemListeners import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporterManager import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners import net.horizonsend.ion.server.features.machine.CryoPods +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners import net.horizonsend.ion.server.features.space.encounters.EncounterManager @@ -28,7 +29,6 @@ import net.horizonsend.ion.server.listener.misc.ChatListener import net.horizonsend.ion.server.listener.misc.EntityListener import net.horizonsend.ion.server.listener.misc.FurnaceListener import net.horizonsend.ion.server.listener.misc.HeadListener -import net.horizonsend.ion.server.listener.misc.InteractListener import net.horizonsend.ion.server.listener.misc.InventoryListener import net.horizonsend.ion.server.listener.misc.JoinLeaveListener import net.horizonsend.ion.server.listener.misc.MiscListeners @@ -53,7 +53,7 @@ val listeners: List = listOf( BlockListener, EntityListener, FurnaceListener, - InteractListener, + NewPoweredMultiblock.Companion, InventoryListener, BowHitListener, From 78494e156c9229252d6d75844f9f79e0af63d4ef Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 01:07:25 -0500 Subject: [PATCH 135/500] organize multiblocks --- .../server/features/machine/AntiAirCannons.kt | 4 +- .../server/features/machine/AreaShields.kt | 2 +- .../features/multiblock/MultiblockAccess.kt | 2 +- .../multiblock/MultiblockRegistration.kt | 94 +++++++++---------- .../features/multiblock/old/Multiblocks.kt | 24 ++--- .../{starshipweapon => }/EntityMultiblock.kt | 2 +- .../multiblock/type/NewPoweredMultiblock.kt | 1 - .../PyrotechnicMachine.kt | 2 +- .../{ => active}/AntiAirCannonMultiblock.kt | 6 +- .../projectile/AntiAirCannonProjectile.kt | 2 +- .../passive}/areashield/AreaShield.kt | 2 +- .../passive}/areashield/AreaShield10.kt | 4 +- .../passive}/areashield/AreaShield20.kt | 4 +- .../passive}/areashield/AreaShield30.kt | 4 +- .../passive}/areashield/AreaShield5.kt | 4 +- .../type/fluid/ElectrolysisMultiblock.kt | 2 +- .../collector/PipedGasCollectorMultiblock.kt | 2 +- .../fluid/storage/FluidStorageMultiblock.kt | 5 +- .../multiblock/type/misc/MobDefender.kt | 2 +- .../multiblock/type/misc/TestMultiblock.kt | 2 +- .../type/power/storage/PowerCellMultiblock.kt | 2 +- .../LandingGearMultiblock.kt | 3 +- .../{misc => starship}/OdometerMultiblock.kt | 3 +- .../SubsystemMultiblock.kt | 2 +- .../checklist/BargeReactorMultiBlock.kt | 2 +- .../BattleCruiserReactorMultiblock.kt | 2 +- .../checklist/CruiserReactorMultiblock.kt | 2 +- .../AmplifiedGravityWellMultiblock.kt | 2 +- .../gravitywell/GravityWellMultiblock.kt | 2 +- .../StandardGravityWellMultiblock.kt | 2 +- .../hyperdrive/HyperdriveMultiblock.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass1.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass2.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass3.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass4.kt | 2 +- .../mininglasers/MiningLaserMultiblock.kt | 4 +- .../MiningLaserMultiblockTier1.kt | 2 +- .../MiningLaserMultiblockTier2.kt | 2 +- .../MiningLaserMultiblockTier3.kt | 2 +- .../MiningLaserMultiblockTier4.kt | 2 +- .../NavigationComputerMultiblock.kt | 2 +- .../NavigationComputerMultiblockAdvanced.kt | 2 +- .../NavigationComputerMultiblockBasic.kt | 2 +- .../SignlessStarshipWeaponMultiblock.kt | 3 +- .../LaserCannonStarshipWeaponMultiblock.kt | 4 +- .../PlasmaCannonStarshipWeaponMultiblock.kt | 4 +- .../PulseCannonStarshipWeaponMultiblock.kt | 4 +- .../CapitalBeamStarshipWeaponMultiblock.kt | 4 +- .../weapon}/event/CthulhuBeamMultiblock.kt | 2 +- .../weapon}/event/FireWaveWeaponMultiblock.kt | 0 .../FlamethrowerStarshipWeaponMultiblock.kt | 4 +- .../event/GazeStarshipWeaponMultiblock.kt | 0 .../MiniPhaserStarshipWeaponMultiblock.kt | 4 +- .../PumpkinCannonStarshipWeaponMultiblock.kt | 4 +- .../SkullThrowerStarshipWeaponMultiblock.kt | 0 .../event/SonicMissileWeaponMultiblock.kt | 4 +- .../AIHeavyLaserStarshipWeaponMultiblock.kt | 4 +- .../heavy/AIPhaserStarshipWeaponMultiblock.kt | 4 +- .../ArsenalRocketStarshipWeaponMultiblock.kt | 4 +- .../heavy/DoomsdayDeviceWeaponMultiblock.kt | 0 .../HeavyLaserStarshipWeaponMultiblock.kt | 4 +- .../heavy/PhaserStarshipWeaponMultiblock.kt | 4 +- .../heavy/RocketStarshipWeaponMultiblock.kt | 4 +- .../heavy/TorpedoStarshipWeaponMultiblock.kt | 4 +- .../PointDefenseStarshipWeaponMultiblock.kt | 4 +- .../weapon}/turret/CycleTurretMultiblock.kt | 0 .../DisintegratorBeamWeaponMultiblock.kt | 0 .../weapon}/turret/HeavyTurretMultiblock.kt | 2 +- .../weapon}/turret/IonTurretMultiblock.kt | 2 +- .../weapon}/turret/LightTurretMultiblock.kt | 2 +- .../turret/LogisticTurretMultiblock.kt | 0 .../weapon}/turret/QuadTurretMultiblock.kt | 2 +- .../weapon}/turret/RotatingMultiblock.kt | 2 +- .../weapon}/turret/TriTurretMultiblock.kt | 2 +- .../weapon}/turret/TurretBaseMultiblock.kt | 0 .../weapon}/turret/TurretMultiblock.kt | 4 +- .../world/ChunkMultiblockManager.kt | 2 +- .../server/features/starship/Interdiction.kt | 2 +- .../ion/server/features/starship/Starship.kt | 6 +- .../starship/active/SubsystemDetector.kt | 23 +++-- .../checklist/BargeReactorSubsystem.kt | 5 +- .../BattlecruiserReactorSubsystem.kt | 2 +- .../checklist/CruiserReactorSubsystem.kt | 2 +- .../subsystem/misc/GravityWellSubsystem.kt | 2 +- .../subsystem/misc/HyperdriveSubsystem.kt | 2 +- .../subsystem/misc/MiningLaserSubsystem.kt | 2 +- .../subsystem/misc/NavCompSubsystem.kt | 2 +- .../ion/server/features/transport/Wires.kt | 3 +- .../multiblock/MultiblockEntityInitializer.kt | 2 +- 89 files changed, 180 insertions(+), 180 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => }/EntityMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{cosmeticmultiblocks => cosmetic}/PyrotechnicMachine.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/{ => active}/AntiAirCannonMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/{ => active}/projectile/AntiAirCannonProjectile.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => defense/passive}/areashield/AreaShield.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => defense/passive}/areashield/AreaShield10.kt (76%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => defense/passive}/areashield/AreaShield20.kt (85%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => defense/passive}/areashield/AreaShield30.kt (85%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => defense/passive}/areashield/AreaShield5.kt (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{misc => starship}/LandingGearMultiblock.kt (87%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{misc => starship}/OdometerMultiblock.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship}/SubsystemMultiblock.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/checklist/BargeReactorMultiBlock.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/checklist/BattleCruiserReactorMultiblock.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/checklist/CruiserReactorMultiblock.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/gravitywell/AmplifiedGravityWellMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/gravitywell/GravityWellMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/gravitywell/StandardGravityWellMultiblock.kt (92%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/hyperdrive/HyperdriveMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/hyperdrive/HyperdriveMultiblockClass1.kt (90%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/hyperdrive/HyperdriveMultiblockClass2.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/hyperdrive/HyperdriveMultiblockClass3.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/hyperdrive/HyperdriveMultiblockClass4.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/mininglasers/MiningLaserMultiblock.kt (95%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/mininglasers/MiningLaserMultiblockTier1.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/mininglasers/MiningLaserMultiblockTier2.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/mininglasers/MiningLaserMultiblockTier3.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/mininglasers/MiningLaserMultiblockTier4.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/navigationcomputer/NavigationComputerMultiblock.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/navigationcomputer/NavigationComputerMultiblockAdvanced.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{ => starship}/navigationcomputer/NavigationComputerMultiblockBasic.kt (89%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/SignlessStarshipWeaponMultiblock.kt (88%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/cannon/LaserCannonStarshipWeaponMultiblock.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/cannon/PlasmaCannonStarshipWeaponMultiblock.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/cannon/PulseCannonStarshipWeaponMultiblock.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/CapitalBeamStarshipWeaponMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/CthulhuBeamMultiblock.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/FireWaveWeaponMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/FlamethrowerStarshipWeaponMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/GazeStarshipWeaponMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/MiniPhaserStarshipWeaponMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/PumpkinCannonStarshipWeaponMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/SkullThrowerStarshipWeaponMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/event/SonicMissileWeaponMultiblock.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/AIPhaserStarshipWeaponMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/ArsenalRocketStarshipWeaponMultiblock.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/DoomsdayDeviceWeaponMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/HeavyLaserStarshipWeaponMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/PhaserStarshipWeaponMultiblock.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/RocketStarshipWeaponMultiblock.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/heavy/TorpedoStarshipWeaponMultiblock.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/misc/PointDefenseStarshipWeaponMultiblock.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/CycleTurretMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/DisintegratorBeamWeaponMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/HeavyTurretMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/IonTurretMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/LightTurretMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/LogisticTurretMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/QuadTurretMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/RotatingMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/TriTurretMultiblock.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/TurretBaseMultiblock.kt (100%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{starshipweapon => starship/weapon}/turret/TurretMultiblock.kt (99%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AntiAirCannons.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AntiAirCannons.kt index a6df368bf8..71d9d1aff9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AntiAirCannons.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AntiAirCannons.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.machine import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannonBaseMultiblock -import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonTurretMultiblock import net.horizonsend.ion.server.features.starship.control.movement.PlayerStarshipControl import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index 16a5e70cc5..a163c8d3eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.machine import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isInRange import org.bukkit.Color diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 5b355ebbfa..3205cb3d0b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -16,8 +16,8 @@ import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.getMultiblockEntity import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.removeMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index ec0e7c86db..f841832066 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -5,37 +5,25 @@ import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield10 -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield20 -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield30 -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield5 -import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock -import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield10 +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield20 +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield30 +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield5 import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass1 -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass2 -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass3 -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblockClass4 import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender -import net.horizonsend.ion.server.features.multiblock.type.misc.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass08Left @@ -49,37 +37,49 @@ import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBa import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerCellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.LaserCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PlasmaCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon.PulseCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CapitalBeamStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.FlamethrowerStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.HorizontalPumpkinCannonStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.MiniPhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.SonicMissileWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIHeavyLaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.AIPhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.BottomArsenalStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.DownwardRocketStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.HeavyLaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.HorizontalRocketStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.PhaserStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.TopArsenalStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.TorpedoStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.UpwardRocketStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockBottom -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockSide -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc.PointDefenseStarshipWeaponMultiblockTop -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomHeavyTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomIonTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomLightTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomQuadTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.BottomTriTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopHeavyTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopIonTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopLightTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopQuadTurretMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TopTriTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.LandingGearMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.OdometerMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BattleCruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass1 +import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass2 +import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass3 +import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass4 +import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced +import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblockBasic +import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon.LaserCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon.PlasmaCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon.PulseCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.CapitalBeamStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.FlamethrowerStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.HorizontalPumpkinCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.MiniPhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.SonicMissileWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.AIHeavyLaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.AIPhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.BottomArsenalStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.DownwardRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.HeavyLaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.HorizontalRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.PhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.TopArsenalStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.TorpedoStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.UpwardRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.misc.PointDefenseStarshipWeaponMultiblockBottom +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.misc.PointDefenseStarshipWeaponMultiblockSide +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.misc.PointDefenseStarshipWeaponMultiblockTop +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.BottomHeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.BottomIonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.BottomLightTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.BottomQuadTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.BottomTriTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TopHeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TopIonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TopLightTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TopQuadTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TopTriTurretMultiblock import net.horizonsend.ion.server.miscellaneous.utils.multimapOf object MultiblockRegistration : IonServerComponent() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 493b985c11..4ffab2c7a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -17,7 +17,7 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPres import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.defense.AntiAirCannonBaseMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 @@ -30,23 +30,12 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.planter.Plant import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.gravitywell.AmplifiedGravityWellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.gravitywell.StandardGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier1Top -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier2Top -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Bottom -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Side -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblockTier3Top import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock @@ -64,6 +53,17 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinter import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.AmplifiedGravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.StandardGravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Top import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt index e8d7cec3e2..9ca0795efe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon +package net.horizonsend.ion.server.features.multiblock.type import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt index 67f5bc1cd5..ad09841b6a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.server.features.gear.setPower import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.listener.SLEventListener import org.bukkit.block.Sign import org.bukkit.event.EventHandler diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt index 862c9f59ae..4f187d2fac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmeticmultiblocks/PyrotechnicMachine.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.cosmeticmultiblocks +package net.horizonsend.ion.server.features.multiblock.type.cosmetic import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt index 94dd8bc281..ff16fd093e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/AntiAirCannonMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.defense +package net.horizonsend.ion.server.features.multiblock.type.defense.active import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.userError @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.features.multiblock.type.defense.projectile.AntiAirCannonProjectile -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.RotatingMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.active.projectile.AntiAirCannonProjectile +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.RotatingMultiblock import net.horizonsend.ion.server.features.starship.control.movement.PlayerStarshipControl import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/projectile/AntiAirCannonProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/projectile/AntiAirCannonProjectile.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/projectile/AntiAirCannonProjectile.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/projectile/AntiAirCannonProjectile.kt index 1ee3102900..7715c64219 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/projectile/AntiAirCannonProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/projectile/AntiAirCannonProjectile.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.defense.projectile +package net.horizonsend.ion.server.features.multiblock.type.defense.active.projectile import net.horizonsend.ion.common.database.Oid import net.horizonsend.ion.common.database.cache.nations.NationCache diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index a94e33fc02..61d49bc83d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.areashield +package net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.IonServer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield10.kt similarity index 76% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield10.kt index ce2c7b6e7d..8e4417f668 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield10.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield10.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.type.areashield +package net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -object AreaShield10 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 10) { +object AreaShield10 : AreaShield(radius = 10) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield20.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield20.kt index 62c1ac963d..a5db7713ef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield20.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield20.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.type.areashield +package net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -object AreaShield20 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 20) { +object AreaShield20 : AreaShield(radius = 20) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield30.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield30.kt index fb2722d899..1508a8abff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield30.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield30.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.type.areashield +package net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -object AreaShield30 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 30) { +object AreaShield30 : AreaShield(radius = 30) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield5.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield5.kt index 324ac065f0..d6f5af283a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/areashield/AreaShield5.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield5.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.type.areashield +package net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -object AreaShield5 : net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield(radius = 5) { +object AreaShield5 : AreaShield(radius = 5) { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index c7f920eecf..0937ce8b2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -9,8 +9,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidSt import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.SingleFluidStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 05025f13cf..583789bde3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidSt import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.CategoryRestrictedInternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory.GAS import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 8d36264974..6978cdc65c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.UnlimitedInternalStorage -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -14,7 +14,8 @@ import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.World import org.bukkit.block.BlockFace -abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityMultiblock { +abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), + EntityMultiblock { override val name: String = "tank" override val alternativeDetectionNames: Array = arrayOf("gastank", "fluidtank") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 8b94f679dd..387355ac95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.Location diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt index 085ce4da9e..75b444c117 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt @@ -9,8 +9,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index fbdb8aad09..c1ab2649ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt similarity index 87% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt index 2609b7f032..548bdd9ef3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/LandingGearMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt @@ -1,8 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.misc +package net.horizonsend.ion.server.features.multiblock.type.starship import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.LandingGearSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt index 6cb8fb970d..6f9fd81f7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/OdometerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt @@ -1,11 +1,10 @@ -package net.horizonsend.ion.server.features.multiblock.type.misc +package net.horizonsend.ion.server.features.multiblock.type.starship import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.OdometerSubsystem import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/SubsystemMultiblock.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/SubsystemMultiblock.kt index 3dd91dfe03..08b0991a63 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SubsystemMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/SubsystemMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon +package net.horizonsend.ion.server.features.multiblock.type.starship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt index 5c878c65cf..a54b1df8f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BargeReactorMultiBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.checklist +package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt index a643dc8bc0..2e244df8bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/BattleCruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.checklist +package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt index 6ba6f4c62a..d361b12ef5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/checklist/CruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.checklist +package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt index 690d28e608..b14d874a90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/AmplifiedGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gravitywell +package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/GravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/GravityWellMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt index 7271547b6a..dd6ef2961c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/GravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gravitywell +package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt similarity index 92% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt index 402fc2714b..34d033de96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/gravitywell/StandardGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.gravitywell +package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt index 62a0d0d705..50d0704dd8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.hyperdrive +package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.gui.custom.navigation.NavigationSystemMapGui import net.horizonsend.ion.server.features.multiblock.Multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt index 0d434df469..e524518387 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.hyperdrive +package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt index 660d07edab..02739fdcf4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.hyperdrive +package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt index a8c72ed2f4..fcca3693c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.hyperdrive +package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt index bec62b6d68..b9c5e8b3f9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/hyperdrive/HyperdriveMultiblockClass4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.hyperdrive +package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt index 5fddb6e4ad..7e801e2692 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.type.mininglasers +package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.MiningLaserSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt index 98f2a720a3..f86208fb46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.mininglasers +package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt index 20cf5bbdd4..fc4b83c1fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.mininglasers +package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt index 7dc0b0e7f7..1b4b3ea82a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.mininglasers +package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt index afc749888c..9478d58928 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/mininglasers/MiningLaserMultiblockTier4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.mininglasers import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt index bf9c1f6f2d..451da4c846 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.navigationcomputer +package net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer import net.horizonsend.ion.server.features.multiblock.Multiblock import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt index fc7f7e46b2..2ad9d9e8b5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockAdvanced.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.navigationcomputer +package net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt similarity index 89% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt index 2a58bb50d6..b06bd4738d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/navigationcomputer/NavigationComputerMultiblockBasic.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.navigationcomputer +package net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt similarity index 88% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt index f2d41b7b7c..e11c1953ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/SignlessStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt @@ -1,6 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.kyori.adventure.text.Component import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/LaserCannonStarshipWeaponMultiblock.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/LaserCannonStarshipWeaponMultiblock.kt index c986a69be2..80b0daf8aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/LaserCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/LaserCannonStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LaserCannonWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt index 30bd1ef4b6..91de06a48e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PlasmaCannonWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt index 9599062b9c..7f84156b69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/cannon/PulseCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.cannon +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PulseCannonWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CapitalBeamStarshipWeaponMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CapitalBeamStarshipWeaponMultiblock.kt index 2d2520fb7e..41a43c3000 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CapitalBeamStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CapitalBeamStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.CapitalBeamWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt index 8c7ca5c5d7..04a73b779f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/CthulhuBeamMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.CthulhuBeamSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FireWaveWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FireWaveWeaponMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FireWaveWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FireWaveWeaponMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FlamethrowerStarshipWeaponMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FlamethrowerStarshipWeaponMultiblock.kt index 87d6b471ad..e7bc7cf759 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/FlamethrowerStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FlamethrowerStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.FlamethrowerWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/GazeStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/GazeStarshipWeaponMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/GazeStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/GazeStarshipWeaponMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/MiniPhaserStarshipWeaponMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/MiniPhaserStarshipWeaponMultiblock.kt index 28eed2ab5b..312bb6cb12 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/MiniPhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/MiniPhaserStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.MiniPhaserWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/PumpkinCannonStarshipWeaponMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/PumpkinCannonStarshipWeaponMultiblock.kt index 7aef0a7f9b..b1f032d35e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/PumpkinCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/PumpkinCannonStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.PumpkinCannonWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SkullThrowerStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SkullThrowerStarshipWeaponMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SkullThrowerStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SkullThrowerStarshipWeaponMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SonicMissileWeaponMultiblock.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SonicMissileWeaponMultiblock.kt index a47d085fa7..cfe1df1ab5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/event/SonicMissileWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SonicMissileWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.SonicMissileWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt index 31c067dd5e..532e0fd962 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/AIHeavyLaserStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.AIHeavyLaserWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/AIPhaserStarshipWeaponMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/AIPhaserStarshipWeaponMultiblock.kt index e6aefec521..0be254ed18 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/AIPhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/AIPhaserStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.AIPhaserWeaponSystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt index 0fc98981e1..9693c2f9f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.ArsenalRocketStarshipWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/DoomsdayDeviceWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/DoomsdayDeviceWeaponMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/DoomsdayDeviceWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/DoomsdayDeviceWeaponMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt index 25fff73420..e144af55d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.HeavyLaserWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt index a525c50c17..9a558d1bc5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/PhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.PhaserWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/RocketStarshipWeaponMultiblock.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/RocketStarshipWeaponMultiblock.kt index 5d301e8493..2f24d2286b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/RocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/RocketStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.RocketWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt index 58e0a9d7f7..7b11ce6f86 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/heavy/TorpedoStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TorpedoWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt index 9acb11fa1d..4b9a6484d1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/misc/PointDefenseStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.misc +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.misc import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PointDefenseSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/CycleTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/CycleTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/DisintegratorBeamWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/DisintegratorBeamWeaponMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/DisintegratorBeamWeaponMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/DisintegratorBeamWeaponMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt index 3d2ff94c24..a744ee0d02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/HeavyTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt index 79c88541a7..5b473b4af3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/IonTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt index 3b22bb7593..6dd6f0bc31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LightTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LogisticTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/LogisticTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt index 3baa98215f..2cd8a33cf1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/QuadTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/RotatingMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/RotatingMultiblock.kt index db1f4b3396..b947f0c608 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/RotatingMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/RotatingMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt index 8b8515c786..675d81c94e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TriTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretBaseMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretBaseMultiblock.kt similarity index 100% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretBaseMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretBaseMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt index 2a3b3f898c..1e83160690 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starshipweapon/turret/TurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.old.Multiblocks -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.damager.Damager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt index 571708a56f..81a0adea04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt index 8b02de5ed1..14f9164b9e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Interdiction.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.CHETHERITE import net.horizonsend.ion.server.features.multiblock.old.Multiblocks -import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index 20e4c64d85..026d49a02b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -21,7 +21,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.configuration.ServerConfiguration import net.horizonsend.ion.server.features.gui.custom.starship.RenameButton.Companion.starshipNameSerializer -import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.features.progression.ShipKillXP import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet @@ -66,13 +66,13 @@ import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.actualType +import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ -import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index 49110c3a47..9b039c7605 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -5,23 +5,22 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.multiblock.old.Multiblocks -import net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield -import net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock -import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock -import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.LandingGearMultiblock -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.SphereShieldMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.LandingGearMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BattleCruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.GravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretBaseMultiblock import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem @@ -306,7 +305,7 @@ object SubsystemDetector { private fun getSignlessStarshipWeaponMultiblock(block: Block, face: BlockFace): SubsystemMultiblock<*>? { return Multiblocks.all() - .filterIsInstance>() + .filterIsInstance>() .firstOrNull { it.blockMatchesStructure(block, face) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BargeReactorSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BargeReactorSubsystem.kt index 53f35df1f3..0d5c81bcb4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BargeReactorSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BargeReactorSubsystem.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.starship.subsystem.checklist +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.AbstractMultiblockSubsystem import org.bukkit.block.Sign -class BargeReactorSubsystem (starship: ActiveStarship, sign: Sign, multiblock: net.horizonsend.ion.server.features.multiblock.type.checklist.BargeReactorMultiBlock) : - AbstractMultiblockSubsystem(starship, sign, multiblock) +class BargeReactorSubsystem (starship: ActiveStarship, sign: Sign, multiblock: BargeReactorMultiBlock) : + AbstractMultiblockSubsystem(starship, sign, multiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BattlecruiserReactorSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BattlecruiserReactorSubsystem.kt index ca08a15fa0..d1caee2f02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BattlecruiserReactorSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/BattlecruiserReactorSubsystem.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.starship.subsystem.checklist -import net.horizonsend.ion.server.features.multiblock.type.checklist.BattleCruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BattleCruiserReactorMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.AbstractMultiblockSubsystem import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/CruiserReactorSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/CruiserReactorSubsystem.kt index 4f46b15962..53f77a1eab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/CruiserReactorSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/checklist/CruiserReactorSubsystem.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.starship.subsystem.checklist -import net.horizonsend.ion.server.features.multiblock.type.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.CruiserReactorMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.AbstractMultiblockSubsystem import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/GravityWellSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/GravityWellSubsystem.kt index 557776e32a..54df767985 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/GravityWellSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/GravityWellSubsystem.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.starship.subsystem.misc -import net.horizonsend.ion.server.features.multiblock.type.gravitywell.GravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.AbstractMultiblockSubsystem import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/HyperdriveSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/HyperdriveSubsystem.kt index 3ad59c09c6..f9143b1485 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/HyperdriveSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/HyperdriveSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.misc import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.CHETHERITE import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.multiblock.type.hyperdrive.HyperdriveMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.hyperspace.Hyperspace import net.horizonsend.ion.server.features.starship.subsystem.AbstractMultiblockSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt index f847811dc8..da7b0eb0e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.machine.AreaShields import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock -import net.horizonsend.ion.server.features.multiblock.type.mininglasers.MiningLaserMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.damager.Damager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/NavCompSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/NavCompSubsystem.kt index 415e66122e..c4f80f8e46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/NavCompSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/NavCompSubsystem.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.starship.subsystem.misc -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.AbstractMultiblockSubsystem import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt index e8d7ee0fb5..c7cfde98a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -299,7 +300,7 @@ object Wires : IonServerComponent() { val destinationFreeSpace = destinationPowerMax - destinationPower val transferLimit = when (destinationMultiblock) { - is net.horizonsend.ion.server.features.multiblock.type.areashield.AreaShield -> transportConfig.wires.maxShieldInput + is AreaShield -> transportConfig.wires.maxShieldInput else -> transportConfig.wires.maxPowerInput } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt index c578cffb6d..cbf46b1e89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/fixers/multiblock/MultiblockEntityInitializer.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.world.data.fixers.multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.world.data.SignDataFixer import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative From 262992d85c74941d34630ba37cfde4f885bb705e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 01:11:16 -0500 Subject: [PATCH 136/500] forgot to select some files --- .../net/horizonsend/ion/server/features/machine/Turrets.kt | 2 +- .../features/starship/subsystem/weapon/TurretWeaponSubsystem.kt | 2 +- .../subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt | 2 +- .../subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt | 2 +- .../subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt | 2 +- .../subsystem/weapon/primary/IonTurretWeaponSubsystem.kt | 2 +- .../subsystem/weapon/primary/LightTurretWeaponSubsystem.kt | 2 +- .../subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt | 2 +- .../weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt | 2 +- .../subsystem/weapon/secondary/RocketWeaponSubsystem.kt | 2 +- .../subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/Turrets.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/Turrets.kt index 323d13b991..e6929d302f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/Turrets.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/Turrets.kt @@ -3,7 +3,7 @@ // import java.util.concurrent.TimeUnit // import net.horizonsend.ion.server.IonServerComponent // import net.horizonsend.ion.server.features.multiblock.Multiblocks -// import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretMultiblock +// import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TurretMultiblock // import net.horizonsend.ion.server.features.starship.active.ActiveStarships // import net.horizonsend.ion.server.features.starship.control.StarshipControl // import net.starlegacy.util.PerPlayerCooldown diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt index 6e30643621..701e14a0f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/TurretWeaponSubsystem.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt index cbddd88bf3..0ba2b23add 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/CapitalBeamWeaponSubsystem.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.event import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.CapitalBeamStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.CapitalBeamStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt index 24600e1cb2..1e5d4b5967 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/PumpkinCannonWeaponSubsystem.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.event import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event.PumpkinCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.PumpkinCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt index 8d8ab7dbe2..8cff88ff93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/HeavyTurretWeaponSubsystem.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.HeavyTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.HeavyTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt index f4c82bfaca..c61b2b4dcc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/IonTurretWeaponSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.IonTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.IonTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt index d1803b12ef..698278b8f9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LightTurretWeaponSubsystem.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.LightTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.LightTurretMultiblock import net.horizonsend.ion.server.features.starship.AutoTurretTargeting.AutoTurretTarget import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt index f0dd6e6a72..6ca6faa550 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/QuadTurretWeaponSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.QuadTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.QuadTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.AmmoConsumingWeaponSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt index f292714c30..07e14801b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/ArsenalRocketStarshipWeaponSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.ArsenalRocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.ArsenalRocketStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt index bc88c0be88..aaa8b8b5f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy.RocketStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.RocketStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt index 2c135542ed..b894bb6582 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/TriTurretWeaponSubsystem.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TriTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TriTurretMultiblock import net.horizonsend.ion.server.features.starship.AutoTurretTargeting.AutoTurretTarget import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem From 90a6482d6c1e5d054aa66c071712e2fc585cc789 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 01:22:11 -0500 Subject: [PATCH 137/500] remove all usages of old multiblock access, besides stuff I'm gonna rewrite anyways --- .../features/multiblock/MultiblockAccess.kt | 2 +- .../gravitywell/GravityWellMultiblock.kt | 28 +++++++++- .../weapon/turret/TurretMultiblock.kt | 7 +-- .../server/features/starship/Interdiction.kt | 55 +------------------ .../starship/active/SubsystemDetector.kt | 16 +++--- 5 files changed, 42 insertions(+), 66 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 3205cb3d0b..b80c386c9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -139,7 +139,7 @@ object MultiblockAccess : IonServerComponent() { return computeMultiblockAtLocation(world, x, y, z, face, true) } - fun getMultiblock(sign: Sign, checkStructure: Boolean, loadChunks: Boolean): Multiblock? { + fun getMultiblock(sign: Sign, checkStructure: Boolean = true, loadChunks: Boolean = false): Multiblock? { if (!checkStructure) { return sign.persistentDataContainer.get(MULTIBLOCK, STRING)?.let { MultiblockRegistration.getByStorageName(it) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt index dd6ef2961c..930915bff1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt @@ -1,21 +1,47 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell +import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.starship.Interdiction +import net.horizonsend.ion.server.features.starship.active.ActiveStarships +import net.horizonsend.ion.server.features.starship.control.movement.StarshipCruising import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.ChatColor import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.sign.Side import org.bukkit.entity.Player +import org.bukkit.event.block.Action +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder -abstract class GravityWellMultiblock : Multiblock() { +abstract class GravityWellMultiblock : Multiblock(), InteractableMultiblock { override fun matchesUndetectedSign(sign: Sign): Boolean { return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[gravwell]", ignoreCase = true) } + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val starship = ActiveStarships.findByPassenger(player) ?: return player.userError("You're not riding the starship") + if (!starship.contains(sign.x, sign.y, sign.z)) return + + if (StarshipCruising.isCruising(starship)) return player.userError("Cannot activate while cruising") + + when (event.action) { + Action.RIGHT_CLICK_BLOCK -> { + Interdiction.toggleGravityWell(starship) + } + + Action.LEFT_CLICK_BLOCK -> { + Interdiction.pulseGravityWell(player, starship, sign) + } + + else -> return + } + } + companion object { private val DISABLED = ChatColor.RED.toString() + "[DISABLED]" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt index 1e83160690..5f791644e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt @@ -4,7 +4,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.old.Multiblocks +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships @@ -26,9 +26,6 @@ import org.bukkit.block.Sign import org.bukkit.block.data.BlockData import org.bukkit.entity.Player import org.bukkit.util.Vector -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin @@ -116,7 +113,7 @@ abstract class TurretMultiblock : Multiblock(), SubsystemMultiblock { event -> - val player = event.player - val block = event.clickedBlock ?: return@listen - if (!block.type.isWallSign) { - return@listen - } - val sign = block.state as Sign - val multiblock = Multiblocks[sign] - if (multiblock !is GravityWellMultiblock) { - return@listen - } - val starship = ActiveStarships.findByPassenger(player) - ?: return@listen player.userError("You're not riding the starship") - if (!starship.contains(block.x, block.y, block.z)) { - return@listen - } - if (StarshipCruising.isCruising(starship)) { - return@listen player.userError("Cannot activate while cruising") - } - when (event.action) { - Action.RIGHT_CLICK_BLOCK -> { - toggleGravityWell(starship) - } - - Action.LEFT_CLICK_BLOCK -> { - pulseGravityWell(player, starship, sign) - } - - else -> return@listen - } - } - } - fun toggleGravityWell(starship: ActiveStarship) { if (StarshipCruising.isCruising(starship)) { starship.setIsInterdicting(false) @@ -105,7 +65,7 @@ object Interdiction : IonServerComponent() { starship.setIsInterdicting(!starship.isInterdicting) } - private fun pulseGravityWell(player: Player, starship: ActiveStarship, sign: Sign) { + fun pulseGravityWell(player: Player, starship: ActiveStarship, sign: Sign) { val world = sign.world if (!world.ion.hasFlag(WorldFlag.SPACE_WORLD)) { @@ -133,17 +93,8 @@ object Interdiction : IonServerComponent() { } for (cruisingShip in ActiveStarships.getInWorld(world)) { - if (cruisingShip !is ActiveControlledStarship) { - continue - } - - if (cruisingShip == starship) { - continue - } - - if (!StarshipCruising.isCruising(cruisingShip)) { - continue - } + if (cruisingShip == starship) continue + if (!StarshipCruising.isCruising(cruisingShip)) continue val controlLoc = cruisingShip.playerPilot?.location ?: starship.centerOfMass.toLocation(starship.world) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index 9b039c7605..2c92a630ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -4,12 +4,13 @@ import net.horizonsend.ion.common.database.schema.Cryopod import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock -import net.horizonsend.ion.server.features.multiblock.old.Multiblocks +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractMagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.SphereShieldMultiblock @@ -21,6 +22,7 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.Cr import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretBaseMultiblock import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem @@ -133,7 +135,7 @@ object SubsystemDetector { private fun detectSign(starship: ActiveControlledStarship, block: Block) { val sign = block.state as Sign - if (Multiblocks.getFromPDC(sign) is AreaShield) { + if (MultiblockAccess.getFast(sign) is AreaShield) { throw ActiveStarshipFactory.StarshipActivationException("Starships cannot fly with area shields!") } @@ -156,7 +158,7 @@ object SubsystemDetector { return } - val multiblock = Multiblocks[sign] ?: return + val multiblock = MultiblockAccess.getFast(sign) ?: return when (multiblock) { is SphereShieldMultiblock -> { @@ -294,7 +296,7 @@ object SubsystemDetector { return null } - val multiblock = Multiblocks[sign] + val multiblock = MultiblockAccess.getMultiblock(sign) if (multiblock !is SubsystemMultiblock<*>) { return null @@ -304,8 +306,8 @@ object SubsystemDetector { } private fun getSignlessStarshipWeaponMultiblock(block: Block, face: BlockFace): SubsystemMultiblock<*>? { - return Multiblocks.all() - .filterIsInstance>() + return MultiblockRegistration.getAllMultiblocks() + .filterIsInstance>() .firstOrNull { it.blockMatchesStructure(block, face) } } From 11555c47467ec565a06c6dff583d0055528e9656 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 01:24:38 -0500 Subject: [PATCH 138/500] remove unused stuff from old multiblocks --- .../features/multiblock/old/Multiblocks.kt | 88 ------------------- 1 file changed, 88 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 4ffab2c7a6..1fd69f565a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -67,13 +67,10 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe -import net.horizonsend.ion.server.miscellaneous.utils.isSign import org.bukkit.World import org.bukkit.block.Sign import org.bukkit.block.sign.Side @@ -81,7 +78,6 @@ import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.block.Action -import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.EquipmentSlot import org.bukkit.persistence.PersistentDataContainer @@ -179,40 +175,6 @@ object Multiblocks : IonServerComponent() { multiblocks[name] = multiblock } - private fun registerAlternateName(name: String, multiblock: Multiblock) { - if (multiblocks.containsKey(name)) { - throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[name]}, new: $multiblock") - } - - multiblocks[name] = multiblock - } - - // Access - - /** - * Get a multiblock by its identifying name - **/ - fun getMultiblockByName(name: String): Multiblock = multiblocks[name]!! - - /** Check if a sign has been registered as a multiblock, if so, return that value */ - fun getFromPDC(sign: Sign): Multiblock? { - return getFromPDC(sign.persistentDataContainer) - } - - /** Check if a pdc, if so, return that value */ - fun getFromPDC(pdc: PersistentDataContainer): Multiblock? { - val data = pdc.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return null - - return getMultiblockByName(data) - } - - /** - * Get all registered multiblocks - **/ - fun all(): List = multiblocks.values.toList() - - // End access - /** * Map of world UUIDs to a map of block keys to Multiblock types * @@ -221,20 +183,6 @@ object Multiblocks : IonServerComponent() { **/ private val multiblockLocationCache: MutableMap> = Object2ObjectOpenHashMap() - /** - * Get a previously found multiblock at this location - **/ - fun getCached(world: World, x: Int, y: Int, z: Int): Multiblock? { - return getCached(world, toBlockKey(x, y, z)) - } - - /** - * Get a previously found multiblock at this location - **/ - fun getCached(world: World, key: Long): Multiblock? { - return multiblockLocationCache.getOrPut(world.uid) { Object2ObjectOpenHashMap() }[key] - } - /** * Get a multiblock from the sign **/ @@ -242,13 +190,6 @@ object Multiblocks : IonServerComponent() { getFromSignPosition(sign.world, sign.x, sign.y, sign.z, checkStructure, loadChunks) } - /** - * Get a multiblock from the sign position - **/ - operator fun get(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean = true, loadChunks: Boolean = false) = runBlocking { - getFromSignPosition(world, x, y, z, checkStructure, loadChunks) - } - /** * Checks against the multiblock cache for a multiblock at a position * @@ -354,25 +295,6 @@ object Multiblocks : IonServerComponent() { } } - @EventHandler - fun onPlayerBreakBlock(event: BlockBreakEvent) { - if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return - val sign = event.block.state as? Sign ?: return - - runBlocking { //TODO replace this - val multiblock = getFromSignPosition( - sign.world, - sign.x, - sign.y, - sign.z, - checkStructure = true, - loadChunks = false - ) ?: return@runBlocking - - removeMultiblock(multiblock, sign) - } - } - /** * Called upon the creation of a new multiblock * @@ -392,14 +314,4 @@ object Multiblocks : IonServerComponent() { sign.isWaxed = true sign.update() } - - /** Upon a multiblock being removed */ - fun removeMultiblock(multiblock: Multiblock, sign: Sign) = Tasks.sync { - val (x, y, z) = Multiblock.getOrigin(sign) - - val chunkX = x.shr(4) - val chunkZ = z.shr(4) - - val chunk = sign.world.ion.getChunk(chunkX, chunkZ) ?: return@sync - } } From d56478f44af2f82c99c7bcdf9565a6b53611024d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 03:02:31 -0500 Subject: [PATCH 139/500] new display handler system --- .../features/client/elsed/DisplayHandlers.kt | 34 ++++++++ .../client/elsed/TextDisplayHandler.kt | 75 ++++++++++++++++++ .../features/client/elsed/display/Display.kt | 79 +++++++++++++++++++ .../client/elsed/display/FluidDisplay.kt | 40 ++++++++++ .../client/elsed/display/PowerDisplay.kt | 38 +++++++++ .../multiblock/entity/MultiblockEntity.kt | 9 ++- .../type/fluids/storage/InternalStorage.kt | 21 +++++ .../type/power/UpdatedPowerDisplayEntity.kt | 9 +++ .../type/fluid/ElectrolysisMultiblock.kt | 6 +- .../type/power/storage/PowerBankMultiblock.kt | 31 +++++--- 10 files changed, 327 insertions(+), 15 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt new file mode 100644 index 0000000000..33a4610afb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.client.elsed + +import net.horizonsend.ion.server.features.client.elsed.display.Display +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import org.bukkit.block.Sign + +object DisplayHandlers { + fun newSignOverlay(sign: Sign) { + + } + + fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg display: Display): TextDisplayHandler { + val signDirection = entity.structureDirection.oppositeFace + val signBlock = MultiblockEntity.getSignFromOrigin(entity.getOrigin(), entity.structureDirection) + + val offset = signDirection.direction.multiply(0.39) + + return TextDisplayHandler( + entity.world, + signBlock.x.toDouble() + 0.5 - offset.x, + signBlock.y.toDouble() + 0.4, + signBlock.z.toDouble() + 0.5 - offset.z, + *display + ) + } + + fun newMultiText() { + + } + + fun newSingleText() { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt new file mode 100644 index 0000000000..3d1e52723e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt @@ -0,0 +1,75 @@ +package net.horizonsend.ion.server.features.client.elsed + +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities +import net.horizonsend.ion.server.features.client.elsed.display.Display +import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.Display.TextDisplay +import org.bukkit.Bukkit +import org.bukkit.World +import java.util.UUID + +class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: Double, vararg display: Display) { + private val displays = listOf(*display) + + private var shownPlayers = mutableSetOf() + + fun update(entity: TextDisplay) { + val chunk = entity.level().world.getChunkAtIfLoaded(x.toInt().shr(4), z.toInt().shr(4)) ?: return + val playerChunk = chunk.minecraft.playerChunk ?: return + + val viewers = playerChunk.getPlayers(false).toSet() + val newPlayers = viewers.filterNot { shownPlayers.contains(it.uuid) } + val old = viewers.filter { shownPlayers.contains(it.uuid) } + + for (player in newPlayers) { + broadcast(player, entity) + } + + for (player in old) { + update(player, entity) + } + + shownPlayers = viewers.mapTo(mutableSetOf()) { it.uuid } + } + + private fun update(player: ServerPlayer, entity: TextDisplay) { + entity.entityData.refresh(player) + } + + private fun broadcast(player: ServerPlayer, entity: TextDisplay) { + ClientDisplayEntities.sendEntityPacket(player, entity) + shownPlayers.add(player.uuid) + } + + fun update() { + displays.forEach { + update(it.entity) + } + } + + fun remove() { + displays.forEach { + for (shownPlayer in shownPlayers) Bukkit.getPlayer(shownPlayer)?.minecraft?.connection?.send( + ClientboundRemoveEntitiesPacket(it.entity.id) + ) + + it.deRegister() + } + + shownPlayers.clear() + } + + fun register(): TextDisplayHandler { + displays.forEach { + it.setParent(this) + it.register() + } + + // TODO schedule updates + + return this + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt new file mode 100644 index 0000000000..961f04474a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt @@ -0,0 +1,79 @@ +package net.horizonsend.ion.server.features.client.elsed.display + +import io.papermc.paper.adventure.PaperAdventure +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData +import net.horizonsend.ion.server.features.client.elsed.TextDisplayHandler +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component +import net.minecraft.world.entity.Display.TextDisplay +import net.minecraft.world.entity.EntityType +import org.bukkit.Color +import org.bukkit.block.BlockFace +import org.bukkit.craftbukkit.v1_20_R3.CraftServer +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay +import org.bukkit.util.Transformation +import org.joml.Quaternionf +import org.joml.Vector3f + +abstract class Display( + private val offsetLeft: Double, + private val offsetUp: Double, + private val offsetBack: Double, + val facing: BlockFace, + val scale: Float +) { + protected lateinit var handler: TextDisplayHandler + lateinit var entity: TextDisplay; private set + + fun setParent(parent: TextDisplayHandler) { + this.handler = parent + val rightFace = facing.rightFace + + val offsetX = rightFace.modX * offsetLeft + facing.modX * offsetBack + val offsetY = offsetUp + val offsetZ = rightFace.modZ * offsetLeft + facing.modZ * offsetBack + + entity = CraftTextDisplay( + IonServer.server as CraftServer, + TextDisplay(EntityType.TEXT_DISPLAY, parent.world.minecraft) + ).apply { + billboard = org.bukkit.entity.Display.Billboard.FIXED + viewRange = 5.0f + brightness = org.bukkit.entity.Display.Brightness(15, 15) + teleportDuration = 0 + backgroundColor = Color.fromARGB(0x00000000) + alignment = org.bukkit.entity.TextDisplay.TextAlignment.CENTER + + transformation = Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector2d(this@Display.facing.direction.toVector3f()), + Vector3f(scale), + Quaternionf() + ) + }.getNMSData(parent.x + offsetX, parent.y + offsetY, parent.z + offsetZ) + } + + /** Registers this display handler */ + abstract fun register() + + /** Registers this display handler */ + abstract fun deRegister() + + abstract fun getText(): Component + + private fun setText(text: Component) { + entity.text = PaperAdventure.asVanilla(text) + } + + fun display() { + if (!::handler.isInitialized) return + + println("Displaying $this") + + setText(getText()) + handler.update(entity) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt new file mode 100644 index 0000000000..488bcb8bab --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt @@ -0,0 +1,40 @@ +package net.horizonsend.ion.server.features.client.elsed.display + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.block.BlockFace + +class FluidDisplay( + val storage: StorageContainer, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + face: BlockFace, + scale: Float, + val title: Component? = null +) : Display(offsetLeft, offsetUp, offsetBack, face, scale) { + private val updateHandler: (InternalStorage) -> Unit = { + display() + } + + override fun register() { + storage.storage.registerUpdateHandler(updateHandler) + } + + override fun deRegister() { + storage.storage.removeUpdateHandler(updateHandler) + } + + override fun getText(): Component { + return title?.let { ofChildren(it, Component.newline(), formatFluid()) } ?: formatFluid() + } + + private fun formatFluid(): Component { + val amount = storage.storage.getAmount() + return ofChildren(text(amount, NamedTextColor.GREEN), text("L", NamedTextColor.GRAY)) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt new file mode 100644 index 0000000000..65ab6edccd --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt @@ -0,0 +1,38 @@ +package net.horizonsend.ion.server.features.client.elsed.display + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.machine.PowerMachines.prefixComponent +import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.newline +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.block.BlockFace + +class PowerDisplay( + private val multiblockEntity: UpdatedPowerDisplayEntity, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + face: BlockFace, + scale: Float, + val title: Component? = null +): Display(offsetLeft, offsetUp, offsetBack, face, scale) { + private val updateHandler: (UpdatedPowerDisplayEntity) -> Unit = { + display() + } + + override fun register() { + multiblockEntity.displayUpdates.add(updateHandler) + } + + override fun deRegister() { + multiblockEntity.displayUpdates.remove(updateHandler) + } + + override fun getText(): Component { + return title?.let { ofChildren(it, newline(), formatPower()) } ?: formatPower() + } + + private fun formatPower(): Component = ofChildren(prefixComponent, text(multiblockEntity.getPower(), NamedTextColor.GREEN)) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 05de3a1ff8..e4be923c3f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -110,7 +110,14 @@ abstract class MultiblockEntity( * Gets the sign of this multiblock **/ fun getSign(): Sign? { - return getSignFromOrigin(world,vec3i, structureDirection).state as? Sign + return getSignFromOrigin(world ,vec3i, structureDirection).state as? Sign + } + + /** + * Gets the origin block of this multiblock + **/ + fun getOrigin(): Block { + return world.getBlockAt(x, y, z) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt index 6273bdc344..a01bea46fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt @@ -73,10 +73,14 @@ abstract class InternalStorage { this.amountUnsafe = corrected if (corrected == 0) setFluid(null) + + runUpdates() } fun setFluid(fluid: PipedFluid?) { this.fluidUnsafe = fluid + + runUpdates() } /** @@ -101,6 +105,23 @@ abstract class InternalStorage { destination.set(NamespacedKeys.FLUID_AMOUNT, PersistentDataType.INTEGER, amount) } + private val updateHandlers = mutableListOf<(InternalStorage) -> Unit>() + + fun registerUpdateHandler(handler: (InternalStorage) -> Unit) { + updateHandlers.add(handler) + } + + fun removeUpdateHandler(handler: (InternalStorage) -> Unit) { + updateHandlers.remove(handler) + } + + fun getUpdateHandlers(): List<(InternalStorage) -> Unit> = updateHandlers + + /** Notify update handlers of an update */ + fun runUpdates() { + updateHandlers.forEach { it.invoke(this) } + } + override fun toString(): String { return "${javaClass.simpleName}[capacity= ${getCapacity()} fluid= (${getStoredFluid()}, ${getAmount()})]" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt new file mode 100644 index 0000000000..87a50e137f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.power + +interface UpdatedPowerDisplayEntity : PoweredMultiblockEntity { + val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> + + override fun updatePowerVisually() { + displayUpdates.forEach { it.invoke(this) } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 0937ce8b2d..41b6225af1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -173,9 +173,9 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock Unit> = mutableListOf() + + val displayHandler = newMultiblockSignOverlay( + this, + PowerDisplay(this, +0.0, +1.0, 0.0, structureDirection.oppositeFace, 0.7f), + PowerDisplay(this, +1.0, +0.0, 0.0, structureDirection.oppositeFace, 0.7f), + PowerDisplay(this, -1.0, -1.0, 0.0, structureDirection.oppositeFace, 0.7f), + ).register() + +// override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) override fun onLoad() { - register() +// register() displayHandler.update() } override fun onUnload() { - unRegister() +// unRegister() displayHandler.remove() } override fun handleRemoval() { - unRegister() +// unRegister() displayHandler.remove() } - override fun isValid(): Boolean { - return !removed - } +// override fun isValid(): Boolean { +// return !removed +// } override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) From 05d365d1cf23b43728c6e0016596f47f32945e6a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 13:26:56 -0500 Subject: [PATCH 140/500] fix unable to display multiple --- .../client/elsed/TextDisplayHandler.kt | 47 +------------------ .../features/client/elsed/display/Display.kt | 47 ++++++++++++++++++- .../type/power/storage/PowerBankMultiblock.kt | 6 +-- 3 files changed, 49 insertions(+), 51 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt index 3d1e52723e..1665dff9f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt @@ -1,65 +1,22 @@ package net.horizonsend.ion.server.features.client.elsed -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities import net.horizonsend.ion.server.features.client.elsed.display.Display -import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.Display.TextDisplay -import org.bukkit.Bukkit import org.bukkit.World -import java.util.UUID class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: Double, vararg display: Display) { private val displays = listOf(*display) - private var shownPlayers = mutableSetOf() - - fun update(entity: TextDisplay) { - val chunk = entity.level().world.getChunkAtIfLoaded(x.toInt().shr(4), z.toInt().shr(4)) ?: return - val playerChunk = chunk.minecraft.playerChunk ?: return - - val viewers = playerChunk.getPlayers(false).toSet() - val newPlayers = viewers.filterNot { shownPlayers.contains(it.uuid) } - val old = viewers.filter { shownPlayers.contains(it.uuid) } - - for (player in newPlayers) { - broadcast(player, entity) - } - - for (player in old) { - update(player, entity) - } - - shownPlayers = viewers.mapTo(mutableSetOf()) { it.uuid } - } - - private fun update(player: ServerPlayer, entity: TextDisplay) { - entity.entityData.refresh(player) - } - - private fun broadcast(player: ServerPlayer, entity: TextDisplay) { - ClientDisplayEntities.sendEntityPacket(player, entity) - shownPlayers.add(player.uuid) - } - fun update() { displays.forEach { - update(it.entity) + it.update() } } fun remove() { displays.forEach { - for (shownPlayer in shownPlayers) Bukkit.getPlayer(shownPlayer)?.minecraft?.connection?.send( - ClientboundRemoveEntitiesPacket(it.entity.id) - ) - + it.remove() it.deRegister() } - - shownPlayers.clear() } fun register(): TextDisplayHandler { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt index 961f04474a..0d9218cd03 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt @@ -5,11 +5,15 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData import net.horizonsend.ion.server.features.client.elsed.TextDisplayHandler +import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component +import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket +import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Display.TextDisplay import net.minecraft.world.entity.EntityType +import org.bukkit.Bukkit import org.bukkit.Color import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.v1_20_R3.CraftServer @@ -17,6 +21,7 @@ import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay import org.bukkit.util.Transformation import org.joml.Quaternionf import org.joml.Vector3f +import java.util.UUID abstract class Display( private val offsetLeft: Double, @@ -25,6 +30,8 @@ abstract class Display( val facing: BlockFace, val scale: Float ) { + var shownPlayers = mutableSetOf() + protected lateinit var handler: TextDisplayHandler lateinit var entity: TextDisplay; private set @@ -68,12 +75,48 @@ abstract class Display( entity.text = PaperAdventure.asVanilla(text) } + fun remove() { + for (shownPlayer in shownPlayers) Bukkit.getPlayer(shownPlayer)?.minecraft?.connection?.send( + ClientboundRemoveEntitiesPacket(entity.id) + ) + + shownPlayers.clear() + } + fun display() { if (!::handler.isInitialized) return - println("Displaying $this") + println("Displaying at ${entity.x}, ${entity.y}, ${entity.z}") setText(getText()) - handler.update(entity) + update() + } + + fun update() { + val chunk = entity.level().world.getChunkAtIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return + val playerChunk = chunk.minecraft.playerChunk ?: return + + val viewers = playerChunk.getPlayers(false).toSet() + val newPlayers = viewers.filterNot { shownPlayers.contains(it.uuid) } + val old = viewers.filter { shownPlayers.contains(it.uuid) } + + for (player in newPlayers) { + broadcast(player) + } + + for (player in old) { + update(player) + } + + shownPlayers = viewers.mapTo(mutableSetOf()) { it.uuid } + } + + private fun update(player: ServerPlayer) { + entity.entityData.refresh(player) + } + + private fun broadcast(player: ServerPlayer) { + ClientDisplayEntities.sendEntityPacket(player, entity) + shownPlayers.add(player.uuid) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 2fb54e3fd1..9cb026615d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -113,11 +113,9 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), /*SimpleTextDisplayPoweredMultiblockEntity*/ UpdatedPowerDisplayEntity { override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() - val displayHandler = newMultiblockSignOverlay( + private val displayHandler = newMultiblockSignOverlay( this, - PowerDisplay(this, +0.0, +1.0, 0.0, structureDirection.oppositeFace, 0.7f), - PowerDisplay(this, +1.0, +0.0, 0.0, structureDirection.oppositeFace, 0.7f), - PowerDisplay(this, -1.0, -1.0, 0.0, structureDirection.oppositeFace, 0.7f), + PowerDisplay(this, +0.0, +0.0, 0.0, structureDirection.oppositeFace, 0.7f) ).register() // override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) From bca6e7b6a385c66dbbeb58e211ecba35fa88e470 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 13:48:54 -0500 Subject: [PATCH 141/500] add display to piped gas collector --- .../features/client/elsed/display/Display.kt | 2 -- .../collector/PipedGasCollectorMultiblock.kt | 21 +++++++++++++++++++ .../type/power/storage/PowerBankMultiblock.kt | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt index 0d9218cd03..d00bfad06d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt @@ -86,8 +86,6 @@ abstract class Display( fun display() { if (!::handler.isInitialized) return - println("Displaying at ${entity.x}, ${entity.y}, ${entity.z}") - setText(getText()) update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 583789bde3..d30e35f776 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.collector import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.elsed.DisplayHandlers +import net.horizonsend.ion.server.features.client.elsed.display.FluidDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -115,6 +117,25 @@ object PipedGasCollectorMultiblock : Multiblock(), loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), ) + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + FluidDisplay(getNamedStorage("tank_1"), +0.0, +0.10, 0.0, structureDirection.oppositeFace, 0.45f), + FluidDisplay(getNamedStorage("tank_2"), +0.0, -0.00, 0.0, structureDirection.oppositeFace, 0.45f), + FluidDisplay(getNamedStorage("tank_3"), +0.0, -0.10, 0.0, structureDirection.oppositeFace, 0.45f) + ).register() + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + private val worldConfig get() = world.ion.configuration.gasConfiguration override suspend fun tickAsync() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 9cb026615d..23f29e5cfd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -115,7 +115,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM private val displayHandler = newMultiblockSignOverlay( this, - PowerDisplay(this, +0.0, +0.0, 0.0, structureDirection.oppositeFace, 0.7f) + PowerDisplay(this, +0.0, +0.0, +0.0, structureDirection.oppositeFace, 0.5f) ).register() // override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) From 45cf59b457c2e275387464f07c1080abb524e9f6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Sep 2024 14:25:01 -0500 Subject: [PATCH 142/500] display improvements, add to ElectrolysisMultiblock --- .../features/client/elsed/display/Display.kt | 39 +++++++------- .../display/fluid/ComplexFluidDisplay.kt | 30 +++++++++++ .../elsed/display/{ => fluid}/FluidDisplay.kt | 16 +++--- .../elsed/display/fluid/SimpleFluidDisplay.kt | 21 ++++++++ .../type/fluid/ElectrolysisMultiblock.kt | 53 +++++++++++++++++-- .../collector/PipedGasCollectorMultiblock.kt | 18 ++----- .../type/power/storage/PowerBankMultiblock.kt | 2 +- .../features/transport/fluids/PipedFluid.kt | 2 + .../transport/fluids/types/GasPipedFluid.kt | 2 + 9 files changed, 136 insertions(+), 47 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/{ => fluid}/FluidDisplay.kt (74%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt index d00bfad06d..b86506da69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt @@ -35,32 +35,35 @@ abstract class Display( protected lateinit var handler: TextDisplayHandler lateinit var entity: TextDisplay; private set + open fun createEntity(parent: TextDisplayHandler): CraftTextDisplay = CraftTextDisplay( + IonServer.server as CraftServer, + TextDisplay(EntityType.TEXT_DISPLAY, parent.world.minecraft) + ).apply { + billboard = org.bukkit.entity.Display.Billboard.FIXED + viewRange = 5.0f + brightness = org.bukkit.entity.Display.Brightness(15, 15) + teleportDuration = 0 + backgroundColor = Color.fromARGB(0x00000000) + alignment = org.bukkit.entity.TextDisplay.TextAlignment.CENTER + + transformation = Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector2d(this@Display.facing.direction.toVector3f()), + Vector3f(scale), + Quaternionf() + ) + } + fun setParent(parent: TextDisplayHandler) { this.handler = parent + val rightFace = facing.rightFace val offsetX = rightFace.modX * offsetLeft + facing.modX * offsetBack val offsetY = offsetUp val offsetZ = rightFace.modZ * offsetLeft + facing.modZ * offsetBack - entity = CraftTextDisplay( - IonServer.server as CraftServer, - TextDisplay(EntityType.TEXT_DISPLAY, parent.world.minecraft) - ).apply { - billboard = org.bukkit.entity.Display.Billboard.FIXED - viewRange = 5.0f - brightness = org.bukkit.entity.Display.Brightness(15, 15) - teleportDuration = 0 - backgroundColor = Color.fromARGB(0x00000000) - alignment = org.bukkit.entity.TextDisplay.TextAlignment.CENTER - - transformation = Transformation( - Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(this@Display.facing.direction.toVector3f()), - Vector3f(scale), - Quaternionf() - ) - }.getNMSData(parent.x + offsetX, parent.y + offsetY, parent.z + offsetZ) + entity = createEntity(parent).getNMSData(parent.x + offsetX, parent.y + offsetY, parent.z + offsetZ) } /** Registers this display handler */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt new file mode 100644 index 0000000000..f2d0ea63ba --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.client.elsed.display.fluid + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.elsed.TextDisplayHandler +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.newline +import org.bukkit.Color +import org.bukkit.block.BlockFace +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay + +class ComplexFluidDisplay( + storage: StorageContainer, + val title: Component, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + face: BlockFace, + scale: Float +) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, face, scale) { + override fun createEntity(parent: TextDisplayHandler): CraftTextDisplay { + return super.createEntity(parent).apply { + backgroundColor = Color.fromARGB(0x00BBBBBB) + } + } + + override fun getText(): Component { + return ofChildren(title, newline(), formatFluid()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/FluidDisplay.kt similarity index 74% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/FluidDisplay.kt index 488bcb8bab..c0e5f4db99 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/FluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/FluidDisplay.kt @@ -1,6 +1,7 @@ -package net.horizonsend.ion.server.features.client.elsed.display +package net.horizonsend.ion.server.features.client.elsed.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.elsed.display.Display import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component @@ -8,14 +9,13 @@ import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace -class FluidDisplay( +abstract class FluidDisplay( val storage: StorageContainer, offsetLeft: Double, offsetUp: Double, offsetBack: Double, face: BlockFace, - scale: Float, - val title: Component? = null + scale: Float ) : Display(offsetLeft, offsetUp, offsetBack, face, scale) { private val updateHandler: (InternalStorage) -> Unit = { display() @@ -29,12 +29,8 @@ class FluidDisplay( storage.storage.removeUpdateHandler(updateHandler) } - override fun getText(): Component { - return title?.let { ofChildren(it, Component.newline(), formatFluid()) } ?: formatFluid() - } - - private fun formatFluid(): Component { + protected fun formatFluid(): Component { val amount = storage.storage.getAmount() - return ofChildren(text(amount, NamedTextColor.GREEN), text("L", NamedTextColor.GRAY)) + return ofChildren(text(amount, NamedTextColor.GOLD), text("L", NamedTextColor.DARK_GRAY)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt new file mode 100644 index 0000000000..ec79b0582f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt @@ -0,0 +1,21 @@ +package net.horizonsend.ion.server.features.client.elsed.display.fluid + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.empty +import net.kyori.adventure.text.Component.space +import org.bukkit.block.BlockFace + +class SimpleFluidDisplay( + storage: StorageContainer, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + face: BlockFace, + scale: Float +) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, face, scale) { + override fun getText(): Component { + return ofChildren(formatFluid(), space(), storage.storage.getStoredFluid()?.displayName ?: empty()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 41b6225af1..8c3a722e5c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -1,6 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.features.client.elsed.DisplayHandlers +import net.horizonsend.ion.server.features.client.elsed.display.PowerDisplay +import net.horizonsend.ion.server.features.client.elsed.display.fluid.ComplexFluidDisplay +import net.horizonsend.ion.server.features.client.elsed.display.fluid.SimpleFluidDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -8,15 +12,17 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMu import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.SingleFluidStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 @@ -35,8 +41,9 @@ import org.bukkit.block.data.Bisected.Half.TOP import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataType -object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { +object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { override val name: String = "ElectrolysisMultiblock" override val alternativeDetectionNames: Array = arrayOf("Electrolysis") @@ -140,8 +147,19 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock Unit> = mutableListOf() + override val capacities: Array = arrayOf( loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER)), loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN)), loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN)) ) + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerDisplay(this, +0.0, +0.0, +0.0, structureDirection.oppositeFace, 0.45f), + SimpleFluidDisplay(getNamedStorage("water_tank"), +0.0, -0.10, +0.0, structureDirection.oppositeFace, 0.45f), + ComplexFluidDisplay(getNamedStorage("hydrogen_tank"), text("Hydrogen"), +1.0, +0.0, +0.0, structureDirection.oppositeFace, 0.5f), + ComplexFluidDisplay(getNamedStorage("oxygen_tank"), text("Oxygen"), -1.0, +0.0, +0.0, structureDirection.oppositeFace, 0.5f) + ).register() + private val hydrogenStorage by lazy { getNamedStorage("hydrogen_tank") } private val oxygenStorage by lazy { getNamedStorage("oxygen_tank") } private val waterStorage by lazy { getNamedStorage("water_tank") } @@ -188,6 +218,19 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf( loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), @@ -119,9 +111,9 @@ object PipedGasCollectorMultiblock : Multiblock(), private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, - FluidDisplay(getNamedStorage("tank_1"), +0.0, +0.10, 0.0, structureDirection.oppositeFace, 0.45f), - FluidDisplay(getNamedStorage("tank_2"), +0.0, -0.00, 0.0, structureDirection.oppositeFace, 0.45f), - FluidDisplay(getNamedStorage("tank_3"), +0.0, -0.10, 0.0, structureDirection.oppositeFace, 0.45f) + SimpleFluidDisplay(getNamedStorage("tank_1"), +0.0, +0.10, 0.0, structureDirection.oppositeFace, 0.45f), + SimpleFluidDisplay(getNamedStorage("tank_2"), +0.0, -0.00, 0.0, structureDirection.oppositeFace, 0.45f), + SimpleFluidDisplay(getNamedStorage("tank_3"), +0.0, -0.10, 0.0, structureDirection.oppositeFace, 0.45f) ).register() override fun onLoad() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 23f29e5cfd..2c293b59f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -110,7 +110,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM structureDirection: BlockFace, override val maxPower: Int, override var powerUnsafe: Int = 0 - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), /*SimpleTextDisplayPoweredMultiblockEntity*/ UpdatedPowerDisplayEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), UpdatedPowerDisplayEntity { override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() private val displayHandler = newMultiblockSignOverlay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt index f5183ccc00..0d629e5ec4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.transport.fluids import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.kyori.adventure.text.Component abstract class PipedFluid(val identifier: String) { + abstract val displayName: Component abstract val categories: Array override fun toString(): String { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt index 9afdf235fe..31bd0157e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.fluids.types import net.horizonsend.ion.server.features.gas.type.Gas import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.kyori.adventure.text.Component import java.util.function.Supplier class GasPipedFluid( @@ -11,5 +12,6 @@ class GasPipedFluid( ) : PipedFluid(identifier) { override val categories: Array = arrayOf(FluidCategory.GAS) + override val displayName: Component get() = gas.displayName val gas get() = gasSupplier.get() } From 0a213581180035f7d59625c72d505a4b134b5863 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Sep 2024 00:09:24 -0500 Subject: [PATCH 143/500] organize a bit --- .../type/fluid/ElectrolysisMultiblock.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 8c3a722e5c..46a505e19a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -195,18 +195,18 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock Date: Wed, 4 Sep 2024 00:19:25 -0500 Subject: [PATCH 144/500] remove background --- .../client/elsed/display/fluid/ComplexFluidDisplay.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt index f2d0ea63ba..9611790208 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt @@ -1,13 +1,10 @@ package net.horizonsend.ion.server.features.client.elsed.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.elsed.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline -import org.bukkit.Color import org.bukkit.block.BlockFace -import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay class ComplexFluidDisplay( storage: StorageContainer, @@ -18,11 +15,6 @@ class ComplexFluidDisplay( face: BlockFace, scale: Float ) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, face, scale) { - override fun createEntity(parent: TextDisplayHandler): CraftTextDisplay { - return super.createEntity(parent).apply { - backgroundColor = Color.fromARGB(0x00BBBBBB) - } - } override fun getText(): Component { return ofChildren(title, newline(), formatFluid()) From c40b6ad0523ca5d2a1947aac023eb3dea41f5bb5 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Sep 2024 01:03:42 -0500 Subject: [PATCH 145/500] remove old display handler method in favor of modular one --- .../display/container/DisplayHandlerHolder.kt | 21 ----- .../display/container/DisplayHandlers.kt | 26 ------ .../display/container/TextDisplayHandler.kt | 86 ------------------- .../client/display/modular/DisplayHandlers.kt | 83 ++++++++++++++++++ .../modular}/TextDisplayHandler.kt | 8 +- .../modular}/display/Display.kt | 4 +- .../modular/display/PowerEntityDisplay.kt} | 4 +- .../modular/display/PowerFlowMeterDisplay.kt | 21 +++++ .../display/fluid/ComplexFluidDisplay.kt | 2 +- .../modular}/display/fluid/FluidDisplay.kt | 4 +- .../display/fluid/SimpleFluidDisplay.kt | 2 +- .../features/client/elsed/DisplayHandlers.kt | 34 -------- .../type/fluids/storage/InternalStorage.kt | 2 +- .../type/fluids/storage/SingleFluidStorage.kt | 2 + ...impleTextDisplayPoweredMultiblockEntity.kt | 41 --------- .../defense/passive/areashield/AreaShield.kt | 22 +++-- .../type/fluid/ElectrolysisMultiblock.kt | 39 +++++++-- .../collector/PipedGasCollectorMultiblock.kt | 4 +- .../type/power/storage/PowerBankMultiblock.kt | 11 +-- .../transport/fluids/TransportedFluids.kt | 9 +- .../transport/node/power/PowerFlowMeter.kt | 51 +++-------- .../miscellaneous/registrations/Components.kt | 2 +- 22 files changed, 186 insertions(+), 292 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/{elsed => display/modular}/TextDisplayHandler.kt (65%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/{elsed => display/modular}/display/Display.kt (95%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/{elsed/display/PowerDisplay.kt => display/modular/display/PowerEntityDisplay.kt} (92%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/{elsed => display/modular}/display/fluid/ComplexFluidDisplay.kt (88%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/{elsed => display/modular}/display/fluid/FluidDisplay.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/{elsed => display/modular}/display/fluid/SimpleFluidDisplay.kt (89%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt deleted file mode 100644 index 83dee127a0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlerHolder.kt +++ /dev/null @@ -1,21 +0,0 @@ -package net.horizonsend.ion.server.features.client.display.container - -interface DisplayHandlerHolder { - val displayHandler: TextDisplayHandler - - fun refresh() - - fun isValid(): Boolean - - fun removeDisplay() { - displayHandler.remove() - } - - fun register() { - DisplayHandlers.displayHolders.add(this) - } - - fun unRegister() { - DisplayHandlers.displayHolders.remove(this) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt deleted file mode 100644 index f1d6d655ce..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/DisplayHandlers.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.horizonsend.ion.server.features.client.display.container - -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.miscellaneous.utils.Tasks - -object DisplayHandlers : IonServerComponent() { - val displayHolders = mutableListOf() - - override fun onEnable() { - Tasks.asyncRepeat(100L, 100L, ::runUpdates) - } - - private fun runUpdates() { - displayHolders.removeAll { - val toRemove = !it.isValid() - - if (toRemove) it.removeDisplay() - - toRemove - } - - for (displayHolder in displayHolders) { - displayHolder.refresh() - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt deleted file mode 100644 index 1e18c656fa..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/container/TextDisplayHandler.kt +++ /dev/null @@ -1,86 +0,0 @@ -package net.horizonsend.ion.server.features.client.display.container - -import io.papermc.paper.adventure.PaperAdventure -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData -import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.kyori.adventure.text.Component -import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.Display -import net.minecraft.world.entity.EntityType -import org.bukkit.Bukkit -import org.bukkit.Color -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.craftbukkit.v1_20_R3.CraftServer -import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay -import org.bukkit.entity.Display.Billboard -import org.bukkit.entity.Display.Brightness -import org.bukkit.entity.TextDisplay.TextAlignment.CENTER -import org.bukkit.util.Transformation -import org.joml.Quaternionf -import org.joml.Vector3f -import java.util.UUID - -class TextDisplayHandler( - val holder: DisplayHandlerHolder, - val world: World, - var x: Double, - var y: Double, - var z: Double, - val scale: Float, - var facing: BlockFace -) { - private val shownPlayers = mutableListOf() - private val nmsEntity: Display.TextDisplay = - CraftTextDisplay( - IonServer.server as CraftServer, - Display.TextDisplay(EntityType.TEXT_DISPLAY, world.minecraft) - ).apply { - billboard = Billboard.FIXED - viewRange = 5.0f - brightness = Brightness(15, 15) - teleportDuration = 0 - backgroundColor = Color.fromARGB(0x00000000) - alignment = CENTER - - transformation = Transformation( - Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(this@TextDisplayHandler.facing.direction.toVector3f()), - Vector3f(scale), - Quaternionf() - ) - }.getNMSData(x, y, z) - - fun setText(text: Component) { - nmsEntity.text = PaperAdventure.asVanilla(text) - update() - } - - private fun broadcast(player: ServerPlayer) { - ClientDisplayEntities.sendEntityPacket(player, nmsEntity) - shownPlayers.add(player.uuid) - } - - private fun update(player: ServerPlayer) { - nmsEntity.entityData.refresh(player) - } - - fun update() { - val chunk = world.getChunkAtIfLoaded(x.toInt().shr(4), z.toInt().shr(4)) ?: return - val playerChunk = chunk.minecraft.playerChunk ?: return - - for (player in playerChunk.getPlayers(false)) { - if (shownPlayers.contains(player.uuid)) update(player) else broadcast(player) - } - } - - fun remove() { - for (shownPlayer in shownPlayers) Bukkit.getPlayer(shownPlayer)?.minecraft?.connection?.send( - ClientboundRemoveEntitiesPacket(nmsEntity.id) - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt new file mode 100644 index 0000000000..3006f53f63 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -0,0 +1,83 @@ +package net.horizonsend.ion.server.features.client.display.modular + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.client.display.modular.display.Display +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign + +object DisplayHandlers : IonServerComponent() { + + fun newSignOverlay(sign: Sign) { + + } + + fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg display: Display): TextDisplayHandler { + val signDirection = entity.structureDirection.oppositeFace + val signBlock = MultiblockEntity.getSignFromOrigin(entity.getOrigin(), entity.structureDirection) + + val offset = signDirection.direction.multiply(0.39) + + return TextDisplayHandler( + entity.world, + signBlock.x.toDouble() + 0.5 - offset.x, + signBlock.y.toDouble() + 0.4, + signBlock.z.toDouble() + 0.5 - offset.z, + *display + ) + } + + fun newBlockOverlay(world: World, block: Vec3i, direction: BlockFace, vararg display: Display): TextDisplayHandler { + val offset = direction.direction.multiply(0.45) + + val facingBlock = getRelative(toBlockKey(block), direction) + + val x = getX(facingBlock).toDouble() + 0.5 - offset.x + val y = getY(facingBlock).toDouble() + 0.35 + val z = getZ(facingBlock).toDouble() + 0.5 - offset.z + + return TextDisplayHandler( + world, + x, + y, + z, + *display + ) + } + + fun newMultiText() { + + } + + fun newSingleText() { + + } + + private val displayHandlers = mutableListOf() + + fun registerHandler(handler: TextDisplayHandler) { + displayHandlers.add(handler) + } + + fun deRegisterHandler(handler: TextDisplayHandler) { + displayHandlers.remove(handler) + } + + override fun onEnable() { + Tasks.asyncRepeat(100L, 100L, ::runUpdates) + } + + private fun runUpdates() { + for (displayHolder in displayHandlers) { + displayHolder.update() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt similarity index 65% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index 1665dff9f8..358e4c4c41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.client.elsed +package net.horizonsend.ion.server.features.client.display.modular -import net.horizonsend.ion.server.features.client.elsed.display.Display +import net.horizonsend.ion.server.features.client.display.modular.display.Display import org.bukkit.World class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: Double, vararg display: Display) { @@ -17,6 +17,8 @@ class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: it.remove() it.deRegister() } + + DisplayHandlers.deRegisterHandler(this) } fun register(): TextDisplayHandler { @@ -25,7 +27,7 @@ class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: it.register() } - // TODO schedule updates + DisplayHandlers.registerHandler(this) return this } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index b86506da69..bfcbf82f83 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.client.elsed.display +package net.horizonsend.ion.server.features.client.display.modular.display import io.papermc.paper.adventure.PaperAdventure import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData -import net.horizonsend.ion.server.features.client.elsed.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.rightFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt similarity index 92% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt index 65ab6edccd..b9829b56a5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/PowerDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.client.elsed.display +package net.horizonsend.ion.server.features.client.display.modular.display import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.machine.PowerMachines.prefixComponent @@ -9,7 +9,7 @@ import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace -class PowerDisplay( +class PowerEntityDisplay( private val multiblockEntity: UpdatedPowerDisplayEntity, offsetLeft: Double, offsetUp: Double, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt new file mode 100644 index 0000000000..92c16bc17b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt @@ -0,0 +1,21 @@ +package net.horizonsend.ion.server.features.client.display.modular.display + +import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter +import net.kyori.adventure.text.Component +import org.bukkit.block.BlockFace + +class PowerFlowMeterDisplay( + private val meter: PowerFlowMeter, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + face: BlockFace, + scale: Float +): Display(offsetLeft, offsetUp, offsetBack, face, scale) { + override fun register() {} + override fun deRegister() {} + + override fun getText(): Component { + return meter.formatPower() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt similarity index 88% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt index 9611790208..324e34966a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/ComplexFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.client.elsed.display.fluid +package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/FluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt index c0e5f4db99..b107bc92ef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/FluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.client.elsed.display.fluid +package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.elsed.display.Display +import net.horizonsend.ion.server.features.client.display.modular.display.Display import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt similarity index 89% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index ec79b0582f..48e5159381 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.client.elsed.display.fluid +package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt deleted file mode 100644 index 33a4610afb..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/elsed/DisplayHandlers.kt +++ /dev/null @@ -1,34 +0,0 @@ -package net.horizonsend.ion.server.features.client.elsed - -import net.horizonsend.ion.server.features.client.elsed.display.Display -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import org.bukkit.block.Sign - -object DisplayHandlers { - fun newSignOverlay(sign: Sign) { - - } - - fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg display: Display): TextDisplayHandler { - val signDirection = entity.structureDirection.oppositeFace - val signBlock = MultiblockEntity.getSignFromOrigin(entity.getOrigin(), entity.structureDirection) - - val offset = signDirection.direction.multiply(0.39) - - return TextDisplayHandler( - entity.world, - signBlock.x.toDouble() + 0.5 - offset.x, - signBlock.y.toDouble() + 0.4, - signBlock.z.toDouble() + 0.5 - offset.z, - *display - ) - } - - fun newMultiText() { - - } - - fun newSingleText() { - - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt index a01bea46fd..425a0ba9fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt @@ -13,7 +13,7 @@ import org.bukkit.persistence.PersistentDataType **/ abstract class InternalStorage { protected var amountUnsafe: Int = 0 - protected var fluidUnsafe: PipedFluid? = null + protected open var fluidUnsafe: PipedFluid? = null abstract fun getCapacity(): Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt index 04fb092532..0165bed0b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt @@ -3,6 +3,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storag import net.horizonsend.ion.server.features.transport.fluids.PipedFluid class SingleFluidStorage(private val storageCapacity: Int, private val restrictedFluid: PipedFluid) : InternalStorage() { + override var fluidUnsafe: PipedFluid? = restrictedFluid + override fun getCapacity(): Int = storageCapacity override fun canStore(resource: PipedFluid, liters: Int): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt deleted file mode 100644 index aefd615a90..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimpleTextDisplayPoweredMultiblockEntity.kt +++ /dev/null @@ -1,41 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.power - -import net.horizonsend.ion.server.features.client.display.container.DisplayHandlerHolder -import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i - -/** - * Interface providing a simple implementation of a visual display via text display entities. - **/ -interface SimpleTextDisplayPoweredMultiblockEntity : PoweredMultiblockEntity, DisplayHandlerHolder { - override fun updatePowerVisually() { - displayHandler.setText(formatPower()) - } - - override fun refresh() { - updatePowerVisually() - } - - companion object { - fun createTextDisplayHandler(entity: DisplayHandlerHolder): TextDisplayHandler { - require(entity is MultiblockEntity) - - val signDirection = entity.structureDirection.oppositeFace - val signLoc = Vec3i(entity.x, entity.y, entity.z) + Vec3i(signDirection.modX, 0, signDirection.modZ) - - // 70% of the way through the block - val offset = signDirection.direction.multiply(0.39) - - return TextDisplayHandler( - entity, - entity.world, - signLoc.x.toDouble() + 0.5 - offset.x, - signLoc.y.toDouble() + 0.4, - signLoc.z.toDouble() + 0.5 - offset.z, - 0.5f, - signDirection - ) - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 61d49bc83d..c3fa6a74b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -2,12 +2,12 @@ package net.horizonsend.ion.server.features.multiblock.type.defense.passive.area import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimpleTextDisplayPoweredMultiblockEntity.Companion.createTextDisplayHandler +import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager @@ -98,34 +98,32 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< signDirection: BlockFace, override var powerUnsafe: Int, override val maxPower: Int - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), SimpleTextDisplayPoweredMultiblockEntity { - override val displayHandler: TextDisplayHandler = createTextDisplayHandler(this) + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), UpdatedPowerDisplayEntity { + override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, structureDirection.oppositeFace, 0.5f) + ).register() override fun onLoad() { world.ion.multiblockManager.register(this) displayHandler.update() - register() } override fun handleRemoval() { world.ion.multiblockManager.deregister(this) - unRegister() displayHandler.remove() } override fun onUnload() { world.ion.multiblockManager.deregister(this) - unRegister() displayHandler.remove() } - override fun isValid(): Boolean { - return !removed - } - override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(POWER, INTEGER, getPower()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 46a505e19a..40e3852709 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.server.features.client.elsed.DisplayHandlers -import net.horizonsend.ion.server.features.client.elsed.display.PowerDisplay -import net.horizonsend.ion.server.features.client.elsed.display.fluid.ComplexFluidDisplay -import net.horizonsend.ion.server.features.client.elsed.display.fluid.SimpleFluidDisplay +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.fluid.ComplexFluidDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SimpleFluidDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -56,13 +56,20 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock = arrayOf() + }) init { pipedFluids.associateByTo(byIdentifier) { it.identifier } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 9a30ca995f..e929000211 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -5,8 +5,9 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.display.container.DisplayHandlerHolder -import net.horizonsend.ion.server.features.client.display.container.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode @@ -19,10 +20,7 @@ import net.horizonsend.ion.server.features.transport.step.result.MoveForward import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text @@ -34,7 +32,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandler, DisplayHandlerHolder { +class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandler { constructor(network: PowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction @@ -68,8 +66,6 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { addTransferred(TransferredPower(transferred, System.currentTimeMillis())) - - displayHandler.setText(formatPower()) } companion object { @@ -77,7 +73,7 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Second", GREEN)) } - private fun formatPower(): Component { + fun formatPower(): Component { var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) // If no averages, or no power has been moved in 5 seconds, go to 0 @@ -112,41 +108,19 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl return sum / timeDiff } - override lateinit var displayHandler: TextDisplayHandler + lateinit var displayHandler: TextDisplayHandler private fun setupDisplayEntity() { - // 95% of the way to the edge of the block once added to the center of the block, to avoid z fighting - val offset = direction.direction.multiply(0.45) - - val facingBlock = getRelative(position, direction) - - val x = getX(facingBlock).toDouble() + 0.5 - offset.x - val y = getY(facingBlock).toDouble() + 0.35 - val z = getZ(facingBlock).toDouble() + 0.5 - offset.z - - displayHandler = TextDisplayHandler( - this, + displayHandler = DisplayHandlers.newBlockOverlay( network.world, - x, - y, - z, - 0.7f, - direction - ) - } - - override fun refresh() { - if (!::displayHandler.isInitialized) return - displayHandler.setText(formatPower()) - } - - override fun isValid(): Boolean { - return !isDead + toVec3i(position), + direction, + PowerFlowMeterDisplay(this, 0.0, 0.0, 0.0, direction, 0.7f) + ).register() } override fun loadIntoNetwork() { setupDisplayEntity() - register() super.loadIntoNetwork() } @@ -158,7 +132,6 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl } override suspend fun handleRemoval(position: BlockKey) { - unRegister() if (::displayHandler.isInitialized) displayHandler.remove() super.handleRemoval(position) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 1ee24f603c..70e9637eec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.client.display.HudIcons import net.horizonsend.ion.server.features.client.display.modular.MultiBlockDisplay import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.type.weapon.sword.SwordListener -import net.horizonsend.ion.server.features.client.display.container.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.economy.bazaar.Bazaars import net.horizonsend.ion.server.features.economy.bazaar.Merchants import net.horizonsend.ion.server.features.economy.cargotrade.CrateRestrictions From da881c2d1d95cd8bd380f7d1d629a98944e0c706 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Sep 2024 13:31:03 -0500 Subject: [PATCH 146/500] ticking improvements --- .../multiblock/MultiblockRegistration.kt | 3 - .../entity/type/ProcessingMultiblockEntity.kt | 1 + .../AsyncTickingMultiblockEntity.kt | 9 +- .../SyncTickingMultiblockEntity.kt | 20 +--- .../ticked/TickedMultiblockEntityParent.kt | 32 +++++ .../type/fluid/ElectrolysisMultiblock.kt | 6 +- .../collector/PipedGasCollectorMultiblock.kt | 6 +- .../multiblock/type/misc/TestMultiblock.kt | 110 ------------------ .../world/ChunkMultiblockManager.kt | 11 +- .../features/world/chunk/ChunkRegion.kt | 5 +- 10 files changed, 59 insertions(+), 144 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/{ => ticked}/AsyncTickingMultiblockEntity.kt (73%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/{ => ticked}/SyncTickingMultiblockEntity.kt (60%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index f841832066..22d985d332 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -22,7 +22,6 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblo import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.TestMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock @@ -100,8 +99,6 @@ object MultiblockRegistration : IonServerComponent() { } private fun initMultiblocks() { - registerMultiblock(TestMultiblock) - // Power registerMultiblock(PowerBankMultiblockTier1) registerMultiblock(PowerBankMultiblockTier2) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt index 2372c4be5f..a210eb3035 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/AsyncTickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt similarity index 73% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/AsyncTickingMultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt index 1cf70c23d2..97c7231332 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/AsyncTickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt @@ -1,19 +1,14 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type +package net.horizonsend.ion.server.features.multiblock.entity.type.ticked /** * Any multiblock that should be ticked along with the world **/ -interface AsyncTickingMultiblockEntity { +interface AsyncTickingMultiblockEntity : TickedMultiblockEntityParent { /** * The logic that is run upon world tick **/ suspend fun tickAsync() - /** - * - **/ - fun shouldAsyncTick(): Boolean = true - /** * **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt similarity index 60% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt index ca634e0fb2..807ecee79e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/SyncTickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt @@ -1,35 +1,25 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type +package net.horizonsend.ion.server.features.multiblock.entity.type.ticked import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity /** * Any multiblock that should be ticked along with the world **/ -interface SyncTickingMultiblockEntity { +interface SyncTickingMultiblockEntity : TickedMultiblockEntityParent { /** * The logic that is run upon world tick **/ fun tick() - /** - * - **/ - fun shouldTick(): Boolean = true - - /** - * - **/ - fun shouldCheckIntegrity(): Boolean = true - companion object { /** - * Checks whether this entity is able / ready to tick. + * returns whether this entity is able / ready to tick. **/ fun preTick(multiblockEntity: T): Boolean { - if (multiblockEntity !is SyncTickingMultiblockEntity) return false + if (multiblockEntity !is TickedMultiblockEntityParent) return false if (multiblockEntity.shouldCheckIntegrity() && !multiblockEntity.isIntact()) return false - return multiblockEntity.shouldTick() + return multiblockEntity.checkTickInterval() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt new file mode 100644 index 0000000000..2516cd24ed --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt @@ -0,0 +1,32 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.ticked + +interface TickedMultiblockEntityParent { + val tickInterval: Int + var currentTick: Int + + var sleepTicks: Int + + /** + * Returns true if the current tick should be allowed to proceed + **/ + fun checkTickInterval(): Boolean { + if (sleepTicks >= 1) { + sleepTicks-- + + return false + } + + currentTick++ + if (currentTick >= tickInterval) { + currentTick = 0 + return false + } + + return true + } + + /** + * + **/ + fun shouldCheckIntegrity(): Boolean = true +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 40e3852709..20e902833a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -8,11 +8,11 @@ import net.horizonsend.ion.server.features.client.display.modular.display.fluid. import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.SingleFluidStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock @@ -207,6 +207,10 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock Unit> = mutableListOf() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index e13a93599c..ffd2c3a786 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -7,10 +7,10 @@ import net.horizonsend.ion.server.features.client.display.modular.display.fluid. import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.CategoryRestrictedInternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock @@ -103,6 +103,10 @@ object PipedGasCollectorMultiblock : Multiblock(), world: World, structureDirection: BlockFace, ) : MultiblockEntity(manager, PipedGasCollectorMultiblock, x, y, z, world, structureDirection), AsyncTickingMultiblockEntity, FluidStoringEntity { + override val tickInterval: Int = 4 + override var currentTick: Int = 0 + override var sleepTicks: Int = 0 + override val capacities: Array = arrayOf( loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt deleted file mode 100644 index 75b444c117..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/TestMultiblock.kt +++ /dev/null @@ -1,110 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.misc - -import net.horizonsend.ion.common.extensions.success -import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.ai.faction.AIFaction.Companion.PIRATE_DARK_RED -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.front -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.format.TextDecoration -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.block.Sign -import org.bukkit.entity.Player -import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataType - -object TestMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { - override val name: String = "testmulti1" - - override val signText: Array = arrayOf( - Component.text("Removed for brevity", PIRATE_DARK_RED, TextDecoration.BOLD), - null, - null, - null - ) - - override fun MultiblockShape.buildStructure() { - at(0, 0,0 ).type(Material.BEDROCK) - } - - override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): TestMultiblockEntity { - return TestMultiblockEntity( - manager, - world, - x, - y, - z, - structureDirection, - data.getAdditionalData(NamespacedKeys.key("test"), PersistentDataType.STRING) ?: "" - ) - } - - class TestMultiblockEntity( - manager: ChunkMultiblockManager, - world: World, - x: Int, - y: Int, - z: Int, - signOffset: BlockFace, - var string: String - ) : MultiblockEntity(manager, TestMultiblock, x, y, z, world, signOffset), SyncTickingMultiblockEntity { - override fun storeAdditionalData(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.key("test"), PersistentDataType.STRING, string) - } - - var ticks = 0; - - override fun tick() { - ticks++ - - val sign = getSign() - - if (isSignLoaded() && sign == null) { - IonServer.slF4JLogger.warn("No sign at ticking multiblock! [$x, $y, $z] $structureDirection") - - - - return - } - - // If null, its just not loaded - sign?.let { - sign.front().line(2, GsonComponentSerializer.gson().deserializeOrNull(string) ?: Component.text("fallback component", PIRATE_DARK_RED)) - Tasks.sync { sign.update() } - } - } - - override fun toString(): String { - return "TestMultiblockEntity[loc = ${Vec3i(x, y, z)}, signOffset = $structureDirection, string = $string]" - } - } - - override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { - val origin = getOrigin(sign) - val (x, y, z) = origin - - val multi = getMultiblockEntity(sign.world, x, y, z) - - if (multi == null) { - player.userError("NO ENTITY! ORIGIN: $origin") - return - } - - multi.string = GsonComponentSerializer.gson().serialize(player.inventory.itemInMainHand.displayName()) - player.success("Set the multiblock test string to ${GsonComponentSerializer.gson().serialize(player.inventory.itemInMainHand.displayName())}, it will be updated next tick") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt index 81a0adea04..013e05601c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt @@ -5,9 +5,10 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.AsyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity.Companion.preTick import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES @@ -55,14 +56,16 @@ class ChunkMultiblockManager(val chunk: IonChunk) { private fun tickAllMultiblocks() { for ((key, syncTicking) in syncTickingMultiblockEntities) runCatching { - syncTicking.tick() + if (preTick(syncTicking as MultiblockEntity)) syncTicking.tick() }.onFailure { e -> log.warn("Exception ticking multiblock ${syncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") e.printStackTrace() } for ((key, asyncTicking) in asyncTickingMultiblockEntities) runCatching { - MultiblockAccess.multiblockCoroutineScope.launch { asyncTicking.tickAsync() } + MultiblockAccess.multiblockCoroutineScope.launch { + if (preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() + } }.onFailure { e -> log.warn("Exception ticking async multiblock ${asyncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") e.printStackTrace() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index a542b37404..6b7aae51e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.IntervalExecutor import net.horizonsend.ion.server.miscellaneous.utils.Tasks import org.bukkit.Chunk import java.util.concurrent.ConcurrentHashMap @@ -18,7 +17,7 @@ class ChunkRegion(val world: IonWorld) { val size get() = chunks.values.size - val tickChunkTransport = IntervalExecutor(4) { + fun tickChunkTransport() { scope.launch { for ((_, chunk) in chunks) { chunk.transportNetwork.tick() @@ -32,7 +31,7 @@ class ChunkRegion(val world: IonWorld) { fun tick() { lastTicked = System.currentTimeMillis() - tickChunkTransport.invoke() + tickChunkTransport() for ((key, chunk) in chunks) chunk.tick() } From 189bcf826fa70940b8eb6df7146adab0261d7c08 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 5 Sep 2024 21:48:23 -0500 Subject: [PATCH 147/500] add alias to slab or stair --- .../ion/server/features/multiblock/shape/MultiblockShape.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 5d7b395fd0..970fcc032d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -368,8 +368,7 @@ class MultiblockShape { } ) ) - fun anySlabOrStairs() = filteredTypes { it.isSlab || it.isStairs } - + fun anySlabOrStairs() = filteredTypes("any slab or stairs") { it.isSlab || it.isStairs } fun terracottaOrDoubleslab() { BlockRequirement( From f908e9b5572cd05e3d684f03b41d76a304590a51 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 5 Sep 2024 22:19:02 -0500 Subject: [PATCH 148/500] abstract out chunk multiblock manager to allow ship multiblock manager --- .../features/multiblock/MultiblockAccess.kt | 2 +- .../features/multiblock/MultiblockEntities.kt | 4 +- .../multiblock/entity/MultiblockEntity.kt | 4 +- .../entity/type/ProcessingMultiblockEntity.kt | 20 +- .../type/fluids/BasicFluidStoringEntity.kt | 4 +- .../manager/ChunkMultiblockManager.kt | 91 +++++++++ .../MultiblockManager.kt} | 172 ++++++------------ .../manager/ShipMultiblockManager.kt | 16 ++ .../WorldMultiblockManager.kt | 2 +- .../multiblock/type/EntityMultiblock.kt | 4 +- .../defense/passive/areashield/AreaShield.kt | 6 +- .../type/fluid/ElectrolysisMultiblock.kt | 6 +- .../collector/PipedGasCollectorMultiblock.kt | 6 +- .../fluid/storage/FluidStorageMultiblock.kt | 6 +- .../multiblock/type/misc/MobDefender.kt | 6 +- .../type/power/storage/PowerBankMultiblock.kt | 6 +- .../type/power/storage/PowerCellMultiblock.kt | 4 +- .../ion/server/features/world/IonWorld.kt | 2 +- .../server/features/world/chunk/IonChunk.kt | 4 +- 19 files changed, 204 insertions(+), 161 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{world/ChunkMultiblockManager.kt => manager/MultiblockManager.kt} (53%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{world => manager}/WorldMultiblockManager.kt (96%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index b80c386c9c..1265044b6d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -184,7 +184,7 @@ object MultiblockAccess : IonServerComponent() { val chunkZ = z.shr(4) world.ion.getChunk(chunkX, chunkZ)?.let { - it.region.launch { it.multiblockManager.addNewMultiblockEntity(multiblock, x, y, z, structureDirection) } + it.region.launch { it.multiblockManager.handleNewMultiblockEntity(multiblock, x, y, z, structureDirection) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 5fa57a0a0c..4e78d1d6cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import org.bukkit.World @@ -24,7 +24,7 @@ object MultiblockEntities { /** * Add a new multiblock entity to the chunk **/ - fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, entity: (ChunkMultiblockManager) -> MultiblockEntity): Boolean { + fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, entity: (MultiblockManager) -> MultiblockEntity): Boolean { val ionChunk = getIonChunk(world, x, y, z) ?: return false ionChunk.region.launch { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index e4be923c3f..3c3f56034d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -27,7 +27,7 @@ import org.bukkit.block.Sign * @param structureDirection The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( - val manager: ChunkMultiblockManager, + val manager: MultiblockManager, open val multiblock: Multiblock, var x: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt index a210eb3035..d1b632ef7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.World import org.bukkit.block.BlockFace @@ -17,15 +17,15 @@ import org.bukkit.persistence.PersistentDataType * @param currentProgress The current progress of the process **/ abstract class ProcessingMultiblockEntity( - manager: ChunkMultiblockManager, - type: Multiblock, - x: Int, - y: Int, - z: Int, - world: World, - signOffset: BlockFace, - val requiredProgress: Int, - var currentProgress: Int = 0 + manager: MultiblockManager, + type: Multiblock, + x: Int, + y: Int, + z: Int, + world: World, + signOffset: BlockFace, + val requiredProgress: Int, + var currentProgress: Int = 0 ) : MultiblockEntity(manager, type, x, y, z, world, signOffset), SyncTickingMultiblockEntity { //TODO // -recipe system diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index 87ffcaf134..da5caedeb6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import org.bukkit.World @@ -15,7 +15,7 @@ import org.bukkit.block.BlockFace * A simple fluid storing entity with a single main storage **/ abstract class BasicFluidStoringEntity( - manager: ChunkMultiblockManager, + manager: MultiblockManager, multiblock: Multiblock, data: PersistentMultiblockData, x: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt new file mode 100644 index 0000000000..11224de786 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -0,0 +1,91 @@ +package net.horizonsend.ion.server.features.multiblock.manager + +import kotlinx.coroutines.launch +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD +import org.bukkit.World +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType +import org.slf4j.Logger + +class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManager(log) { + override val world: World = chunk.world + + /** + * Logic upon the chunk being saved + **/ + override fun save() { + saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) + } + + override fun getNetwork(type: NetworkType): TransportNetwork { + return type.get(chunk) + } + + init { + loadMultiblocks() + } + + /** + * Save the multiblock data back into the chunk + **/ + private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = MultiblockAccess.multiblockCoroutineScope.launch { + val old = chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) + old?.let { + chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY, it) + } + + val array = multiblockEntities.map { (_, entity) -> + entity.serialize(adapterContext, entity.store()) + }.toTypedArray() + + chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) + } + + /** + * Load the multiblocks from the persistent data container upon chunk load. + **/ + private fun loadMultiblocks() { + val serialized = try { + chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return + } catch (e: IllegalArgumentException) { + log.warn("Could not load chunks multiblocks for $chunk") + if (e.message == "The found tag instance (NBTTagList) cannot store List") { + log.info("Found outdated list tag, removing") + + chunk.inner.persistentDataContainer.remove(STORED_MULTIBLOCK_ENTITIES) + } + + arrayOf() + } catch (e: Throwable) { + // Try to load backup + chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return + } catch (e: Throwable) { + // Give up + return + } + + for (serializedMultiblockData in serialized) { + val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, chunk.inner.persistentDataContainer.adapterContext) + + val multiblock = stored.type as EntityMultiblock<*> + + val entity = multiblock.createEntity(this, stored, chunk.inner.world, stored.x, stored.y, stored.z, stored.signOffset) + + // No need to save a load + addMultiblockEntity(entity, save = false) + } + } + + fun onUnload() { + multiblockEntities.values.forEach { + it.onUnload() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt similarity index 53% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 013e05601c..bea8989901 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.world +package net.horizonsend.ion.server.features.multiblock.manager import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.Multiblock @@ -8,32 +8,32 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity.Companion.preTick import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD +import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataType -import org.slf4j.LoggerFactory +import org.slf4j.Logger import java.util.concurrent.ConcurrentHashMap -class ChunkMultiblockManager(val chunk: IonChunk) { - private val log = LoggerFactory.getLogger("ChunkMutliblockManager[$chunk]") - +abstract class MultiblockManager(val log: Logger) { /** All the loaded multiblock entities of this chunk */ - private val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + protected val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** All the ticked multiblock entities of this chunk */ val syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() val asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + abstract val world: World + + abstract fun save() + /** * Logic upon the chunk being ticked **/ @@ -41,22 +41,49 @@ class ChunkMultiblockManager(val chunk: IonChunk) { tickAllMultiblocks() } + fun getAllMultiblockEntities() = multiblockEntities + + abstract fun getNetwork(type: NetworkType): TransportNetwork + /** - * Logic upon the chunk being saved + * Handles the addition of a multiblock entity **/ - fun save() { - saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) - } + fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true) { + multiblockEntities[entity.locationKey] = entity + + entity.onLoad() - init { - loadMultiblocks() + if (entity is SyncTickingMultiblockEntity) { + syncTickingMultiblockEntities[entity.locationKey] = entity + } + + if (entity is AsyncTickingMultiblockEntity) { + asyncTickingMultiblockEntities[entity.locationKey] = entity + } + + if (save) save() } - fun getAllMultiblockEntities() = multiblockEntities + /** + * Upon the removal of a multiblock sign + **/ + fun removeMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { + val key = toBlockKey(x, y, z) + + val entity = multiblockEntities.remove(key) + entity?.removed = true + + syncTickingMultiblockEntities.remove(key) + asyncTickingMultiblockEntities.remove(key) + + entity?.handleRemoval() + + return entity + } - private fun tickAllMultiblocks() { + protected fun tickAllMultiblocks() { for ((key, syncTicking) in syncTickingMultiblockEntities) runCatching { - if (preTick(syncTicking as MultiblockEntity)) syncTicking.tick() + if (SyncTickingMultiblockEntity.preTick(syncTicking as MultiblockEntity)) syncTicking.tick() }.onFailure { e -> log.warn("Exception ticking multiblock ${syncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") e.printStackTrace() @@ -64,7 +91,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { for ((key, asyncTicking) in asyncTickingMultiblockEntities) runCatching { MultiblockAccess.multiblockCoroutineScope.launch { - if (preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() + if (SyncTickingMultiblockEntity.preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() } }.onFailure { e -> log.warn("Exception ticking async multiblock ${asyncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") @@ -75,10 +102,11 @@ class ChunkMultiblockManager(val chunk: IonChunk) { /** * Add a new multiblock to the chunk data **/ - suspend fun addNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace) { + suspend fun handleNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace) { // Allow smart cast multiblock as Multiblock + // Abort process if one already exists, so it's not overwritten if (isOccupied(x, y, z)) { log.warn("Attempted to place a multiblock where one already existed!") return @@ -88,7 +116,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { val entity = multiblock.createEntity( this, PersistentMultiblockData(x, y, z, multiblock, face), - chunk.inner.world, + world, x, y, z, face ) @@ -97,100 +125,7 @@ class ChunkMultiblockManager(val chunk: IonChunk) { addMultiblockEntity(entity) if (entity is PoweredMultiblockEntity) { - chunk.transportNetwork.powerNetwork.network.handleNewPoweredMultiblock(entity) - } - } - - /** - * Handles the addition of a multiblock entity - **/ - fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true) { - multiblockEntities[entity.locationKey] = entity - - entity.onLoad() - - if (entity is SyncTickingMultiblockEntity) { - syncTickingMultiblockEntities[entity.locationKey] = entity - } - - if (entity is AsyncTickingMultiblockEntity) { - asyncTickingMultiblockEntities[entity.locationKey] = entity - } - - if (save) saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) - } - - /** - * Save the multiblock data back into the chunk - **/ - private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = MultiblockAccess.multiblockCoroutineScope.launch { - val old = chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) - old?.let { - chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY, it) - } - - val array = multiblockEntities.map { (_, entity) -> - entity.serialize(adapterContext, entity.store()) - }.toTypedArray() - - chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) - } - - /** - * Load the multiblocks from the persistent data container upon chunk load. - **/ - private fun loadMultiblocks() { - val serialized = try { - chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return - } catch (e: IllegalArgumentException) { - log.warn("Could not load chunks multiblocks for $chunk") - if (e.message == "The found tag instance (NBTTagList) cannot store List") { - log.info("Found outdated list tag, removing") - - chunk.inner.persistentDataContainer.remove(STORED_MULTIBLOCK_ENTITIES) - } - - arrayOf() - } catch (e: Throwable) { - // Try to load backup - chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return - } catch (e: Throwable) { - // Give up - return - } - - for (serializedMultiblockData in serialized) { - val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, chunk.inner.persistentDataContainer.adapterContext) - - val multiblock = stored.type as EntityMultiblock<*> - - val entity = multiblock.createEntity(this, stored, chunk.inner.world, stored.x, stored.y, stored.z, stored.signOffset) - - // No need to save a load - addMultiblockEntity(entity, save = false) - } - } - - /** - * Upon the removal of a multiblock sign - **/ - fun removeMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { - val key = toBlockKey(x, y, z) - - val entity = multiblockEntities.remove(key) - entity?.removed = true - - syncTickingMultiblockEntities.remove(key) - asyncTickingMultiblockEntities.remove(key) - - entity?.handleRemoval() - - return entity - } - - fun onUnload() { - multiblockEntities.values.forEach { - it.onUnload() + (getNetwork(NetworkType.POWER) as PowerNetwork).handleNewPoweredMultiblock(entity) } } @@ -219,3 +154,4 @@ class ChunkMultiblockManager(val chunk: IonChunk) { fun isOccupied(x: Int, y: Int, z: Int): Boolean = multiblockEntities.containsKey(toBlockKey(x, y, z)) } + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt new file mode 100644 index 0000000000..e033820a33 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -0,0 +1,16 @@ +package net.horizonsend.ion.server.features.multiblock.manager + +import net.horizonsend.ion.server.features.starship.Starship +import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.NetworkType +import org.slf4j.Logger + +class ShipMultiblockManager(val starship: Starship, logger: Logger) : MultiblockManager(logger) { + override val world get() = starship.world + + override fun save() {} + + override fun getNetwork(type: NetworkType): TransportNetwork { + return type.get(starship) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt index 0352e56914..fc36f71208 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/world/WorldMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.world +package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt index 9ca0795efe..8ff3586c83 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.World import org.bukkit.block.BlockFace @@ -19,7 +19,7 @@ interface EntityMultiblock { * Create the multiblock entity using the stored data **/ fun createEntity( - manager: ChunkMultiblockManager, + manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index c3fa6a74b3..a4ac467d1d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -8,9 +8,9 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -74,7 +74,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< "&8Radius: &a$radius" ) - override fun createEntity(manager: ChunkMultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AreaShieldEntity { + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AreaShieldEntity { return AreaShieldEntity( manager, this, @@ -89,7 +89,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< } class AreaShieldEntity( - manager: ChunkMultiblockManager, + manager: MultiblockManager, override val multiblock: AreaShield, x: Int, y: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 20e902833a..e35dc8be89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -13,12 +13,12 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs -import net.horizonsend.ion.server.features.multiblock.world.ChunkMultiblockManager import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER @@ -170,7 +170,7 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock Date: Fri, 6 Sep 2024 01:54:32 -0500 Subject: [PATCH 149/500] transposition of multiblock entities on ships, fix alternative detection names --- .../client/display/modular/DisplayHandlers.kt | 16 ++- .../display/modular/TextDisplayHandler.kt | 29 +++- .../client/display/modular/display/Display.kt | 39 +++++- .../modular/display/PowerEntityDisplay.kt | 4 +- .../modular/display/PowerFlowMeterDisplay.kt | 4 +- .../display/fluid/ComplexFluidDisplay.kt | 4 +- .../modular/display/fluid/FluidDisplay.kt | 4 +- .../display/fluid/SimpleFluidDisplay.kt | 4 +- .../server/features/multiblock/Multiblock.kt | 12 +- .../features/multiblock/MultiblockAccess.kt | 23 ++- .../multiblock/entity/MultiblockEntity.kt | 22 +++ .../ticked/SyncTickingMultiblockEntity.kt | 2 +- .../multiblock/manager/MultiblockManager.kt | 6 +- .../manager/ShipMultiblockManager.kt | 131 +++++++++++++++++- .../manager/WorldMultiblockManager.kt | 25 ++++ .../multiblock/type/EntityMultiblock.kt | 9 ++ .../defense/passive/areashield/AreaShield.kt | 7 +- .../type/fluid/ElectrolysisMultiblock.kt | 20 +-- .../collector/PipedGasCollectorMultiblock.kt | 11 +- .../type/power/storage/PowerBankMultiblock.kt | 7 +- .../starship/DeactivatedPlayerStarships.kt | 2 + .../server/features/starship/FlyableBlocks.kt | 17 +++ .../ion/server/features/starship/Starship.kt | 12 +- .../active/ActiveStarshipMechanics.kt | 1 + .../starship/movement/RotationMovement.kt | 9 ++ .../starship/movement/StarshipMovement.kt | 4 + .../starship/movement/TranslateMovement.kt | 9 ++ .../transport/ShipTransportManager.kt | 20 +++ .../transport/node/power/PowerFlowMeter.kt | 2 +- 29 files changed, 387 insertions(+), 68 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index 3006f53f63..2d602dda1b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -13,6 +13,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.util.Vector +import java.util.concurrent.ConcurrentHashMap object DisplayHandlers : IonServerComponent() { @@ -28,9 +30,11 @@ object DisplayHandlers : IonServerComponent() { return TextDisplayHandler( entity.world, - signBlock.x.toDouble() + 0.5 - offset.x, + signBlock.x.toDouble() + 0.5, signBlock.y.toDouble() + 0.4, - signBlock.z.toDouble() + 0.5 - offset.z, + signBlock.z.toDouble() + 0.5, + Vector(-offset.x, 0.0, -offset.z), + entity.structureDirection.oppositeFace, *display ) } @@ -40,15 +44,17 @@ object DisplayHandlers : IonServerComponent() { val facingBlock = getRelative(toBlockKey(block), direction) - val x = getX(facingBlock).toDouble() + 0.5 - offset.x + val x = getX(facingBlock).toDouble() + 0.5 val y = getY(facingBlock).toDouble() + 0.35 - val z = getZ(facingBlock).toDouble() + 0.5 - offset.z + val z = getZ(facingBlock).toDouble() + 0.5 return TextDisplayHandler( world, x, y, z, + Vector(-offset.x, 0.0, -offset.z), + direction, *display ) } @@ -61,7 +67,7 @@ object DisplayHandlers : IonServerComponent() { } - private val displayHandlers = mutableListOf() + private val displayHandlers = ConcurrentHashMap.newKeySet() fun registerHandler(handler: TextDisplayHandler) { displayHandlers.add(handler) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index 358e4c4c41..7d1a1363f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -1,9 +1,21 @@ package net.horizonsend.ion.server.features.client.display.modular import net.horizonsend.ion.server.features.client.display.modular.display.Display +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import org.bukkit.Location import org.bukkit.World - -class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: Double, vararg display: Display) { +import org.bukkit.block.BlockFace +import org.bukkit.util.Vector + +class TextDisplayHandler( + var world: World, + var anchorX: Double, + var anchorY: Double, + var anchorZ: Double, + var offset: Vector, + var facing: BlockFace, + vararg display: Display +) { private val displays = listOf(*display) fun update() { @@ -31,4 +43,17 @@ class TextDisplayHandler(val world: World, val x: Double, val y: Double, val z: return this } + + fun getLocation() = Location(world, anchorX, anchorY, anchorZ).add(offset) + + fun displace(movement: StarshipMovement) { + offset = movement.displaceVector(offset) + facing = movement.displaceFace(facing) + + for (display in displays) { + display.resetPosition(this) + } + + update() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index bfcbf82f83..7081a6962b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -15,7 +15,6 @@ import net.minecraft.world.entity.Display.TextDisplay import net.minecraft.world.entity.EntityType import org.bukkit.Bukkit import org.bukkit.Color -import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.v1_20_R3.CraftServer import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay import org.bukkit.util.Transformation @@ -27,7 +26,6 @@ abstract class Display( private val offsetLeft: Double, private val offsetUp: Double, private val offsetBack: Double, - val facing: BlockFace, val scale: Float ) { var shownPlayers = mutableSetOf() @@ -48,7 +46,7 @@ abstract class Display( transformation = Transformation( Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(this@Display.facing.direction.toVector3f()), + ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), Vector3f(scale), Quaternionf() ) @@ -57,13 +55,40 @@ abstract class Display( fun setParent(parent: TextDisplayHandler) { this.handler = parent - val rightFace = facing.rightFace + val rightFace = parent.facing.rightFace - val offsetX = rightFace.modX * offsetLeft + facing.modX * offsetBack + val offsetX = rightFace.modX * offsetLeft + parent.facing.modX * offsetBack val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetLeft + facing.modZ * offsetBack + val offsetZ = rightFace.modZ * offsetLeft + parent.facing.modZ * offsetBack - entity = createEntity(parent).getNMSData(parent.x + offsetX, parent.y + offsetY, parent.z + offsetZ) + entity = createEntity(parent).getNMSData( + parent.getLocation().x + offsetX, + parent.getLocation().y + offsetY, + parent.getLocation().z + offsetZ + ) + } + + fun resetPosition(parent: TextDisplayHandler) { + val rightFace = parent.facing.rightFace + + val offsetX = rightFace.modX * offsetLeft + parent.facing.modX * offsetBack + val offsetY = offsetUp + val offsetZ = rightFace.modZ * offsetLeft + parent.facing.modZ * offsetBack + + entity.apply { + setPos( + parent.getLocation().x + offsetX, + parent.getLocation().y + offsetY, + parent.getLocation().z + offsetZ + ) + + setTransformation(com.mojang.math.Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), + Vector3f(scale), + Quaternionf() + )) + } } /** Registers this display handler */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt index b9829b56a5..8bad8567bc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt @@ -7,17 +7,15 @@ import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.block.BlockFace class PowerEntityDisplay( private val multiblockEntity: UpdatedPowerDisplayEntity, offsetLeft: Double, offsetUp: Double, offsetBack: Double, - face: BlockFace, scale: Float, val title: Component? = null -): Display(offsetLeft, offsetUp, offsetBack, face, scale) { +): Display(offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (UpdatedPowerDisplayEntity) -> Unit = { display() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt index 92c16bc17b..a4aee5c4de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt @@ -2,16 +2,14 @@ package net.horizonsend.ion.server.features.client.display.modular.display import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.kyori.adventure.text.Component -import org.bukkit.block.BlockFace class PowerFlowMeterDisplay( private val meter: PowerFlowMeter, offsetLeft: Double, offsetUp: Double, offsetBack: Double, - face: BlockFace, scale: Float -): Display(offsetLeft, offsetUp, offsetBack, face, scale) { +): Display(offsetLeft, offsetUp, offsetBack, scale) { override fun register() {} override fun deRegister() {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt index 324e34966a..618a761d04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt @@ -4,7 +4,6 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline -import org.bukkit.block.BlockFace class ComplexFluidDisplay( storage: StorageContainer, @@ -12,9 +11,8 @@ class ComplexFluidDisplay( offsetLeft: Double, offsetUp: Double, offsetBack: Double, - face: BlockFace, scale: Float -) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, face, scale) { +) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { return ofChildren(title, newline(), formatFluid()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt index b107bc92ef..422ae20c6f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt @@ -7,16 +7,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.block.BlockFace abstract class FluidDisplay( val storage: StorageContainer, offsetLeft: Double, offsetUp: Double, offsetBack: Double, - face: BlockFace, scale: Float -) : Display(offsetLeft, offsetUp, offsetBack, face, scale) { +) : Display(offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (InternalStorage) -> Unit = { display() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index 48e5159381..10f07121b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -5,16 +5,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.space -import org.bukkit.block.BlockFace class SimpleFluidDisplay( storage: StorageContainer, offsetLeft: Double, offsetUp: Double, offsetBack: Double, - face: BlockFace, scale: Float -) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, face, scale) { +) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { return ofChildren(formatFluid(), space(), storage.storage.getStoredFluid()?.displayName ?: empty()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 4c9a43dc99..6bc90f194e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock +import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState @@ -109,9 +110,14 @@ abstract class Multiblock { } open fun matchesUndetectedSign(sign: Sign): Boolean { - return (sign.getSide(Side.FRONT).line(0) as TextComponent) - .content() - .equals("[$name]", ignoreCase = true) + val line = sign.getSide(Side.FRONT).line(0) + val content = (line as? TextComponent)?.content() ?: line.plainText() + + return alternativeDetectionNames + .toMutableList() + .plus(name) + .map { "[$it]" } + .any { it.equals(content, ignoreCase = true) } } open fun setupSign(player: Player, sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 1265044b6d..426262b92c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -9,8 +9,6 @@ import kotlinx.coroutines.SupervisorJob import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.common.utils.text.plainText -import net.horizonsend.ion.common.utils.text.subStringBetween import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.getMultiblockEntity @@ -24,7 +22,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing @@ -212,19 +209,17 @@ object MultiblockAccess : IonServerComponent() { fun tryDetectMultiblock(player: Player, sign: Sign, face: BlockFace? = null, loadChunks: Boolean = false): Multiblock? { val world = sign.world - val blankText = sign.front().line(0).plainText() - val name = blankText.subStringBetween('[', ']') + val possibleMultiblocks = MultiblockRegistration + .getAllMultiblocks() + .filter { it.matchesUndetectedSign(sign) } + + if (possibleMultiblocks.isEmpty()) return null val direction = sign.getFacing().oppositeFace // Get the block that the sign is placed on val originBlock = MultiblockEntity.getOriginFromSign(sign) - // Possible multiblocks from the sign - val possible = MultiblockRegistration.getByDetectionName(name) - - if (possible.isEmpty()) return null - val found = computeMultiblockAtLocation( world, originBlock.x, @@ -232,13 +227,15 @@ object MultiblockAccess : IonServerComponent() { originBlock.z, face, loadChunks = loadChunks, - restrictedList = possible + restrictedList = possibleMultiblocks ) + val named = possibleMultiblocks.first() + if (found == null) { - player.userError("Improperly built $name. Make sure every block is correctly placed!") + player.userError("Improperly built ${named.name}. Make sure every block is correctly placed!") - MultiblockCommand.setupCommand(player, sign, possible.first()) + MultiblockCommand.setupCommand(player, sign, named) return null } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 3c3f56034d..3dc83fabd1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -80,6 +81,8 @@ abstract class MultiblockEntity( /** Logic to be run upon the loading of the chunk holding this entity, or its creation */ open fun onLoad() {} + open fun displaceAdditional(movement: StarshipMovement) {} + /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ @@ -143,6 +146,25 @@ abstract class MultiblockEntity( return world.getBlockAt(x, y, z) } + fun displace(movement: StarshipMovement) { + val newX = movement.displaceX(x, z) + val newY = movement.displaceY(y) + val newZ = movement.displaceZ(z, x) + + this.x = newX + this.y = newY + this.z = newZ + + val world = movement.newWorld + if (world != null) { + this.world = world + } + + this.structureDirection = movement.displaceFace(structureDirection) + + displaceAdditional(movement) + } + companion object { /** Get the multiblock's origin from its sign */ fun getOriginFromSign(sign: Sign): Block { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt index 807ecee79e..e761987345 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt @@ -17,7 +17,7 @@ interface SyncTickingMultiblockEntity : TickedMultiblockEntityParent { **/ fun preTick(multiblockEntity: T): Boolean { if (multiblockEntity !is TickedMultiblockEntityParent) return false - if (multiblockEntity.shouldCheckIntegrity() && !multiblockEntity.isIntact()) return false + if (multiblockEntity.shouldCheckIntegrity() && !multiblockEntity.isIntact(false)) return false return multiblockEntity.checkTickInterval() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index bea8989901..cec32f0a32 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -24,11 +24,11 @@ import java.util.concurrent.ConcurrentHashMap abstract class MultiblockManager(val log: Logger) { /** All the loaded multiblock entities of this chunk */ - protected val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + protected open val multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** All the ticked multiblock entities of this chunk */ - val syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() - val asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + open val syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + open val asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() abstract val world: World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index e033820a33..4dba3be077 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -1,11 +1,28 @@ package net.horizonsend.ion.server.features.multiblock.manager +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.starship.Starship +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.NetworkType -import org.slf4j.Logger +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import java.util.concurrent.ConcurrentHashMap + +class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServer.slF4JLogger) { + override var multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + + /** All the ticked multiblock entities of this chunk */ + override var syncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() + override var asyncTickingMultiblockEntities: ConcurrentHashMap = ConcurrentHashMap() -class ShipMultiblockManager(val starship: Starship, logger: Logger) : MultiblockManager(logger) { override val world get() = starship.world override fun save() {} @@ -13,4 +30,114 @@ class ShipMultiblockManager(val starship: Starship, logger: Logger) : Multiblock override fun getNetwork(type: NetworkType): TransportNetwork { return type.get(starship) } + + init { + loadEntities() + } + + fun loadEntities() { + val worldManager = world.ion.multiblockManager + + starship.iterateBlocks { x, y, z -> + val modernBlockKey = toBlockKey(x, y, z) + val manager = worldManager.getChunkManager(modernBlockKey) ?: return@iterateBlocks + + manager.getAllMultiblockEntities()[modernBlockKey]?.let { + multiblockEntities[modernBlockKey] = it + manager.getAllMultiblockEntities().remove(modernBlockKey) + } ?: return@iterateBlocks + + manager.syncTickingMultiblockEntities[modernBlockKey]?.let { + syncTickingMultiblockEntities[modernBlockKey] = it + manager.syncTickingMultiblockEntities.remove(modernBlockKey) + } + + manager.asyncTickingMultiblockEntities[modernBlockKey]?.let { + asyncTickingMultiblockEntities[modernBlockKey] = it + manager.asyncTickingMultiblockEntities.remove(modernBlockKey) + } + } + } + + fun releaseEntities() { + val manager = world.ion.multiblockManager + + for ((key, multiblockEntity) in multiblockEntities) { + val network = manager.getChunkManager(key) ?: continue + + // If it was lost, don't place it back + if (!multiblockEntity.isIntact(checkSign = true)) { + println("Wasn't intact") + multiblockEntity.handleRemoval() + continue + } + + network.getAllMultiblockEntities()[key] = multiblockEntity + } + + for ((key, multiblockEntity) in syncTickingMultiblockEntities) { + val network = manager.getChunkManager(key) ?: continue + + // If it was lost, don't place it back + if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { + multiblockEntity.handleRemoval() + continue + } + + network.syncTickingMultiblockEntities[key] = multiblockEntity + } + + for ((key, multiblockEntity) in asyncTickingMultiblockEntities) { + val network = manager.getChunkManager(key) ?: continue + + // If it was lost, don't place it back + if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { + multiblockEntity.handleRemoval() + continue + } + + network.asyncTickingMultiblockEntities[key] = multiblockEntity + } + } + + private fun displaceKey(movement: StarshipMovement, key: BlockKey): BlockKey { + val x = getX(key) + val y = getY(key) + val z = getZ(key) + + return toBlockKey( + movement.displaceX(x, z), + movement.displaceY(y), + movement.displaceZ(z, x), + ) + } + + fun displaceEntities(movement: StarshipMovement) { + val newEntities = ConcurrentHashMap() + + for (entry in multiblockEntities) { + val entity = entry.value + entity.displace(movement) + + newEntities[displaceKey(movement, entry.key)] = entity + } + + multiblockEntities = newEntities + + val newSyncTicking = ConcurrentHashMap() + + for (entry in syncTickingMultiblockEntities) { + newSyncTicking[displaceKey(movement, entry.key)] = entry.value + } + + syncTickingMultiblockEntities = newSyncTicking + + val newAsyncTicking = ConcurrentHashMap() + + for (entry in asyncTickingMultiblockEntities) { + newAsyncTicking[displaceKey(movement, entry.key)] = entry.value + } + + asyncTickingMultiblockEntities = newAsyncTicking + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt index fc36f71208..9bd95653d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt @@ -3,6 +3,10 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.LinkedBlockingQueue import kotlin.reflect.KClass @@ -36,4 +40,25 @@ class WorldMultiblockManager(val world: IonWorld) { fun getStoredMultiblocks(): Set> { return worldMultiblocks.keys } + + fun getMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { + val chunk = world.getChunk(x.shr(4), z.shr(4)) ?: return null + val key = toBlockKey(x, y, z) + + return chunk.multiblockManager[key] + } + + fun getMultiblockEntity(key: BlockKey): MultiblockEntity? { + val chunk = world.getChunk(getX(key).shr(4), getZ(key).shr(4)) ?: return null + + return chunk.multiblockManager[key] + } + + fun getChunkManager(key: BlockKey): ChunkMultiblockManager? { + return world.getChunk(getX(key).shr(4), getZ(key).shr(4))?.multiblockManager + } + + fun getChunkManager(x: Int, y: Int, z: Int): ChunkMultiblockManager? { + return world.getChunk(x.shr(4), z.shr(4))?.multiblockManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt index 8ff3586c83..ebf78b7a1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.World import org.bukkit.block.BlockFace @@ -39,6 +40,14 @@ interface EntityMultiblock { fun getMultiblockEntity(sign: Sign): T? { val origin = MultiblockEntity.getOriginFromSign(sign) + val world = sign.world + val ship = ActiveStarships.getInWorld(world).firstOrNull { it.contains(origin.x, origin.y, origin.z) } + + if (ship != null) { + @Suppress("UNCHECKED_CAST") + return ship.multiblockManager[origin.x, origin.y, origin.z] as T? + } + @Suppress("UNCHECKED_CAST") return MultiblockEntities.getMultiblockEntity(origin) as T? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index a4ac467d1d..024b46dfe6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedP import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -103,7 +104,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, structureDirection.oppositeFace, 0.5f) + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() override fun onLoad() { @@ -124,6 +125,10 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< displayHandler.remove() } + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(POWER, INTEGER, getPower()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index e35dc8be89..1f95b6a6aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -19,6 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.type.InteractableMultibloc import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER @@ -226,10 +227,10 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock) in starship.carriedShips) { if (!blocks.isEmpty()) { carriedShipStateMap[ship] = StarshipState.createFromBlocks(world, blocks) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt index 6d20582727..c92640597e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt @@ -47,6 +47,7 @@ import org.bukkit.Material.COAL_BLOCK import org.bukkit.Material.COMPARATOR import org.bukkit.Material.COMPOSTER import org.bukkit.Material.COPPER_BLOCK +import org.bukkit.Material.COPPER_GRATE import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.CREEPER_HEAD import org.bukkit.Material.CREEPER_WALL_HEAD @@ -64,6 +65,7 @@ import org.bukkit.Material.ENDER_CHEST import org.bukkit.Material.END_PORTAL_FRAME import org.bukkit.Material.END_ROD import org.bukkit.Material.EXPOSED_COPPER +import org.bukkit.Material.EXPOSED_COPPER_GRATE import org.bukkit.Material.FARMLAND import org.bukkit.Material.FLETCHING_TABLE import org.bukkit.Material.FLOWER_POT @@ -95,6 +97,7 @@ import org.bukkit.Material.NOTE_BLOCK import org.bukkit.Material.OBSERVER import org.bukkit.Material.OCHRE_FROGLIGHT import org.bukkit.Material.OXIDIZED_COPPER +import org.bukkit.Material.OXIDIZED_COPPER_GRATE import org.bukkit.Material.PEARLESCENT_FROGLIGHT import org.bukkit.Material.PISTON import org.bukkit.Material.PISTON_HEAD @@ -160,10 +163,15 @@ import org.bukkit.Material.VERDANT_FROGLIGHT import org.bukkit.Material.WALL_TORCH import org.bukkit.Material.WATER_CAULDRON import org.bukkit.Material.WAXED_COPPER_BLOCK +import org.bukkit.Material.WAXED_COPPER_GRATE import org.bukkit.Material.WAXED_EXPOSED_COPPER +import org.bukkit.Material.WAXED_EXPOSED_COPPER_GRATE import org.bukkit.Material.WAXED_OXIDIZED_COPPER +import org.bukkit.Material.WAXED_OXIDIZED_COPPER_GRATE import org.bukkit.Material.WAXED_WEATHERED_COPPER +import org.bukkit.Material.WAXED_WEATHERED_COPPER_GRATE import org.bukkit.Material.WEATHERED_COPPER +import org.bukkit.Material.WEATHERED_COPPER_GRATE import org.bukkit.Material.WET_SPONGE import org.bukkit.Material.WHEAT import org.bukkit.Material.WITHER_SKELETON_SKULL @@ -267,6 +275,15 @@ val FLYABLE_BLOCKS: EnumSet = mutableSetOf( WAXED_WEATHERED_COPPER, WAXED_OXIDIZED_COPPER, + COPPER_GRATE, + EXPOSED_COPPER_GRATE, + WEATHERED_COPPER_GRATE, + OXIDIZED_COPPER_GRATE, + WAXED_COPPER_GRATE, + WAXED_EXPOSED_COPPER_GRATE, + WAXED_WEATHERED_COPPER_GRATE, + WAXED_OXIDIZED_COPPER_GRATE, + POTTED_AZURE_BLUET, POTTED_BAMBOO, POTTED_BIRCH_SAPLING, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index 026d49a02b..edadf51244 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -20,6 +20,7 @@ import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.configuration.ServerConfiguration +import net.horizonsend.ion.server.features.multiblock.manager.ShipMultiblockManager import net.horizonsend.ion.server.features.gui.custom.starship.RenameButton.Companion.starshipNameSerializer import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.GravityWellMultiblock import net.horizonsend.ion.server.features.player.CombatTimer @@ -62,6 +63,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.thruster.ThrusterS import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.CustomTurretSubsystem +import net.horizonsend.ion.server.features.transport.ShipTransportManager import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES @@ -106,7 +108,7 @@ import kotlin.math.pow import kotlin.math.roundToInt import kotlin.math.sqrt -class Starship ( +class Starship( val data: StarshipData, var blocks: LongOpenHashSet, val mass: Double, @@ -169,12 +171,20 @@ class Starship ( } //endregion + // Start region transport + val multiblockManager = ShipMultiblockManager(this) + + val transportManager = ShipTransportManager(this) + // Endregion + //region Ship Blocks & Hitbox var hullIntegrity = 1.0 + fun updateHullIntegrity() { currentBlockCount = blocks.count { getBlockTypeSafe(world, blockKeyX(it), blockKeyY(it), blockKeyZ(it))?.isAir != true } + hullIntegrity = currentBlockCount.toDouble() / initialBlockCount.toDouble() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt index 66fb13ecfd..531add690f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipMechanics.kt @@ -112,6 +112,7 @@ object ActiveStarshipMechanics : IonServerComponent() { private fun destroyLowHullIntegrityShips() { ActiveStarships.all().forEach { ship -> ship.updateHullIntegrity() + if (ship.hullIntegrity < MAX_SAFE_HULL_INTEGRITY) { ship.alert("Critical hull integrity failure!") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt index 9e4a8eb7ea..c6c26355e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt @@ -14,6 +14,7 @@ import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause import org.bukkit.util.Vector +import kotlin.math.PI import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin @@ -97,6 +98,14 @@ class RotationMovement(starship: ActiveStarship, val clockwise: Boolean) : Stars } } + override fun displaceFace(face: BlockFace): BlockFace { + return rotateBlockFace(face) + } + + override fun displaceVector(vector: Vector): Vector { + return if (clockwise) vector.clone().rotateAroundY(0.5 * PI) else vector.clone().rotateAroundY(-0.5 * PI) + } + override fun onComplete() { starship.calculateHitbox() for (subsystem in starship.subsystems) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt index f33e17f41b..ea8882a5d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt @@ -37,6 +37,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.rectangle import net.minecraft.world.level.block.state.BlockState import org.bukkit.Location import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.entity.Animals import org.bukkit.entity.Entity import org.bukkit.entity.Item @@ -54,6 +55,8 @@ abstract class StarshipMovement(val starship: ActiveStarship, val newWorld: Worl abstract fun displaceY(oldY: Int): Int abstract fun displaceZ(oldZ: Int, oldX: Int): Int abstract fun displaceLocation(oldLocation: Location): Location + abstract fun displaceFace(face: BlockFace): BlockFace + abstract fun displaceVector(vector: Vector): Vector protected abstract fun movePassenger(passenger: Entity) protected abstract fun onComplete() protected abstract fun blockDataTransform(blockData: BlockState): BlockState @@ -136,6 +139,7 @@ abstract class StarshipMovement(val starship: ActiveStarship, val newWorld: Worl starship.calculateMinMax() updateCenter() updateSubsystems(world2) + starship.multiblockManager.displaceEntities(this) onComplete() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt index 50ca2a4797..f958d2ae20 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt @@ -10,6 +10,7 @@ import net.minecraft.world.level.block.state.BlockState import org.bukkit.Chunk import org.bukkit.Location import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.entity.Entity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerTeleportEvent @@ -75,6 +76,14 @@ class TranslateMovement(starship: ActiveStarship, val dx: Int, val dy: Int, val override fun displaceZ(oldZ: Int, oldX: Int): Int = oldZ + dz + override fun displaceFace(face: BlockFace): BlockFace { + return face + } + + override fun displaceVector(vector: Vector): Vector = vector + .clone() + .add(Vector(dx.toDouble(), dy.toDouble(), dz.toDouble())) + override fun displaceLocation(oldLocation: Location): Location { val newLocation = oldLocation.clone().add(dx, dy, dz) if (newWorld != null) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt new file mode 100644 index 0000000000..a3fd3c6cf2 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.transport + +import net.horizonsend.ion.server.features.starship.Starship +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement + +class ShipTransportManager( + val starship: Starship +) { + init { + load() + } + + fun load() { + + } + + fun displace(movement: StarshipMovement) { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index e929000211..0997785c60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -115,7 +115,7 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl network.world, toVec3i(position), direction, - PowerFlowMeterDisplay(this, 0.0, 0.0, 0.0, direction, 0.7f) + PowerFlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) ).register() } From 5cc9f5b15c30f64f31c8f20bed4a0c0ba70ff30c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 6 Sep 2024 17:10:02 -0500 Subject: [PATCH 150/500] redo how positioning is done for display handlers --- .../client/display/modular/DisplayHandlers.kt | 22 ++++---- .../display/modular/TextDisplayHandler.kt | 29 ++++++++--- .../client/display/modular/display/Display.kt | 52 +++++++++++-------- .../manager/ShipMultiblockManager.kt | 1 - .../type/fluid/ElectrolysisMultiblock.kt | 11 +++- 5 files changed, 71 insertions(+), 44 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index 2d602dda1b..988eff728d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -13,7 +13,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.util.Vector import java.util.concurrent.ConcurrentHashMap object DisplayHandlers : IonServerComponent() { @@ -24,24 +23,21 @@ object DisplayHandlers : IonServerComponent() { fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg display: Display): TextDisplayHandler { val signDirection = entity.structureDirection.oppositeFace - val signBlock = MultiblockEntity.getSignFromOrigin(entity.getOrigin(), entity.structureDirection) - - val offset = signDirection.direction.multiply(0.39) return TextDisplayHandler( entity.world, - signBlock.x.toDouble() + 0.5, - signBlock.y.toDouble() + 0.4, - signBlock.z.toDouble() + 0.5, - Vector(-offset.x, 0.0, -offset.z), - entity.structureDirection.oppositeFace, + entity.x.toDouble() + 0.5, + entity.y.toDouble() + 0.4, + entity.z.toDouble() + 0.5, + offsetRight = 0.0, + offsetUp = 0.0, + offsetForward = 0.61, + signDirection, *display ) } fun newBlockOverlay(world: World, block: Vec3i, direction: BlockFace, vararg display: Display): TextDisplayHandler { - val offset = direction.direction.multiply(0.45) - val facingBlock = getRelative(toBlockKey(block), direction) val x = getX(facingBlock).toDouble() + 0.5 @@ -53,7 +49,9 @@ object DisplayHandlers : IonServerComponent() { x, y, z, - Vector(-offset.x, 0.0, -offset.z), + offsetRight = 0.0, + offsetUp = 0.0, + offsetForward = -0.45, direction, *display ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index 7d1a1363f8..814bccfc3c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -2,21 +2,24 @@ package net.horizonsend.ion.server.features.client.display.modular import net.horizonsend.ion.server.features.client.display.modular.display.Display import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.starship.movement.TranslateMovement +import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Location import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.util.Vector class TextDisplayHandler( var world: World, var anchorX: Double, var anchorY: Double, var anchorZ: Double, - var offset: Vector, + var offsetRight: Double, + var offsetUp: Double, + var offsetForward: Double, var facing: BlockFace, vararg display: Display ) { - private val displays = listOf(*display) + val displays = listOf(*display) fun update() { displays.forEach { @@ -44,11 +47,25 @@ class TextDisplayHandler( return this } - fun getLocation() = Location(world, anchorX, anchorY, anchorZ).add(offset) + fun getLocation(): Location { + val rightFace = facing.rightFace + + val offsetX = rightFace.modX * offsetRight + facing.modX * offsetForward + val offsetY = offsetUp + val offsetZ = rightFace.modZ * offsetRight + facing.modZ * offsetForward + + return Location(world, anchorX + offsetX, anchorY + offsetY, anchorZ + offsetZ) + } fun displace(movement: StarshipMovement) { - offset = movement.displaceVector(offset) - facing = movement.displaceFace(facing) + val oldFace = facing + facing = movement.displaceFace(oldFace) + + if (movement is TranslateMovement) { + anchorX += movement.dx + anchorY += movement.dy + anchorZ += movement.dz + } for (display in displays) { display.resetPosition(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index 7081a6962b..a4f01e59be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -10,10 +10,12 @@ import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket +import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Display.TextDisplay import net.minecraft.world.entity.EntityType import org.bukkit.Bukkit +import org.bukkit.Bukkit.getPlayer import org.bukkit.Color import org.bukkit.craftbukkit.v1_20_R3.CraftServer import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay @@ -23,7 +25,7 @@ import org.joml.Vector3f import java.util.UUID abstract class Display( - private val offsetLeft: Double, + private val offsetRight: Double, private val offsetUp: Double, private val offsetBack: Double, val scale: Float @@ -57,38 +59,42 @@ abstract class Display( val rightFace = parent.facing.rightFace - val offsetX = rightFace.modX * offsetLeft + parent.facing.modX * offsetBack + val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetBack val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetLeft + parent.facing.modZ * offsetBack + val offsetZ = rightFace.modZ * offsetRight + parent.facing.modZ * offsetBack + + val parentLoc = parent.getLocation() entity = createEntity(parent).getNMSData( - parent.getLocation().x + offsetX, - parent.getLocation().y + offsetY, - parent.getLocation().z + offsetZ + parentLoc.x + offsetX, + parentLoc.y + offsetY, + parentLoc.z + offsetZ ) } fun resetPosition(parent: TextDisplayHandler) { val rightFace = parent.facing.rightFace - val offsetX = rightFace.modX * offsetLeft + parent.facing.modX * offsetBack + val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetBack val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetLeft + parent.facing.modZ * offsetBack - - entity.apply { - setPos( - parent.getLocation().x + offsetX, - parent.getLocation().y + offsetY, - parent.getLocation().z + offsetZ - ) - - setTransformation(com.mojang.math.Transformation( - Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), - Vector3f(scale), - Quaternionf() - )) - } + val offsetZ = rightFace.modZ * offsetRight + parent.facing.modZ * offsetBack + + val parentLoc = parent.getLocation() + + entity.teleportTo( + parentLoc.x + offsetX, + parentLoc.y + offsetY, + parentLoc.z + offsetZ + ) + + entity.setTransformation(com.mojang.math.Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), + Vector3f(scale), + Quaternionf() + )) + + shownPlayers.map(::getPlayer).forEach { it?.minecraft?.connection?.send(ClientboundTeleportEntityPacket(entity)) } } /** Registers this display handler */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 4dba3be077..09b2494136 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -67,7 +67,6 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe // If it was lost, don't place it back if (!multiblockEntity.isIntact(checkSign = true)) { - println("Wasn't intact") multiblockEntity.handleRemoval() continue } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 1f95b6a6aa..a5abbc540e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid +import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.fluid.ComplexFluidDisplay @@ -31,6 +33,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.L import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.OPPOSITE import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.RIGHT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.SELF +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor @@ -185,7 +188,11 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock Date: Fri, 6 Sep 2024 17:17:13 -0500 Subject: [PATCH 151/500] tick multiblocks on ships --- .../ion/server/features/multiblock/manager/MultiblockManager.kt | 2 +- .../net/horizonsend/ion/server/features/starship/Starship.kt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index cec32f0a32..8810c65e6b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -81,7 +81,7 @@ abstract class MultiblockManager(val log: Logger) { return entity } - protected fun tickAllMultiblocks() { + private fun tickAllMultiblocks() { for ((key, syncTicking) in syncTickingMultiblockEntities) runCatching { if (SyncTickingMultiblockEntity.preTick(syncTicking as MultiblockEntity)) syncTicking.tick() }.onFailure { e -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index edadf51244..d6b41a7761 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -140,6 +140,7 @@ class Starship( /** Called on each server tick. */ fun tick() { controller.tick() + multiblockManager.tick() subsystems.forEach { it.tick() } } From 1eadc774fbbcd94c5c66cd6e9e5579f8957c08a2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 6 Sep 2024 18:37:38 -0500 Subject: [PATCH 152/500] migrate item chargers, fix furnace multiblocks --- .../multiblock/MultiblockRegistration.kt | 7 + .../features/multiblock/old/Multiblocks.kt | 7 - .../defense/passive/areashield/AreaShield.kt | 5 +- .../type/power/charger/ChargerMultiblock.kt | 158 +++++++++++++----- .../server/listener/misc/FurnaceListener.kt | 6 +- 5 files changed, 125 insertions(+), 58 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 22d985d332..8a0ae5413d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -32,6 +32,9 @@ import net.horizonsend.ion.server.features.multiblock.type.particleshield.Shield import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass30 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass65 import net.horizonsend.ion.server.features.multiblock.type.particleshield.ShieldMultiblockClass85 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 @@ -108,6 +111,10 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(PowerBankMultiblockTier3, "NewPowerBankMultiblockTier3") //TODO testing only - remove on live registerMultiblock(PowerCellMultiblock) + registerMultiblock(ChargerMultiblockTier1) + registerMultiblock(ChargerMultiblockTier2) + registerMultiblock(ChargerMultiblockTier3) + // Gas registerMultiblock(PipedGasCollectorMultiblock) registerMultiblock(ElectrolysisMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 1fd69f565a..b08a408afd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -39,9 +39,6 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMu import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 @@ -109,10 +106,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(PowerFurnaceMultiblockTier2) registerMultiblock(PowerFurnaceMultiblockTier3) - registerMultiblock(ChargerMultiblockTier1) - registerMultiblock(ChargerMultiblockTier2) - registerMultiblock(ChargerMultiblockTier3) - registerMultiblock(CarbonProcessorMultiblock) registerMultiblock(CarbonPrinterMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 024b46dfe6..13d5161c98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -84,8 +84,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< z, world, structureDirection, - data.getAdditionalDataOrDefault(POWER, INTEGER, 0), - maxPower + data.getAdditionalDataOrDefault(POWER, INTEGER, 0) ) } @@ -98,9 +97,9 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< world: World, signDirection: BlockFace, override var powerUnsafe: Int, - override val maxPower: Int ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), UpdatedPowerDisplayEntity { override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() + override val maxPower: Int = multiblock.maxPower private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 7f18dbe951..f9cd76c9e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -1,22 +1,33 @@ package net.horizonsend.ion.server.features.multiblock.type.power.charger +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.custom.items.component.PowerStorage import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType -abstract class ChargerMultiblock(val tierText: String) : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock { protected abstract val tierMaterial: Material protected abstract val powerPerSecond: Int @@ -65,57 +76,116 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), PowerStor furnace: Furnace, sign: Sign ) { - event.isBurning = false - event.burnTime = 0 - val inventory = furnace.inventory - val smelting = inventory.smelting - val power = PowerMachines.getPower(sign) - val item = event.fuel - if (smelting == null || smelting.type != Material.PRISMARINE_CRYSTALS) { - return - } - if (power == 0) { - return - } + val entity = getMultiblockEntity(sign) ?: return - val custom = item.customItem ?: return - if (custom.hasComponent(CustomComponentTypes.POWER_STORAGE)) - handleModern(item, custom, custom.getComponent(CustomComponentTypes.POWER_STORAGE), event, furnace, inventory, sign, power) + entity.handleCharging(event, furnace) } - fun handleModern( - item: ItemStack, - customItem: CustomItem, - powerManager: PowerStorage, - event: FurnaceBurnEvent, - furnace: Furnace, - inventory: FurnaceInventory, - sign: Sign, - power: Int - ) { - if (powerManager.getMaxPower(customItem, item) == powerManager.getPower(item)) { - val result = inventory.result - if (result != null && result.type != Material.AIR) return - inventory.result = event.fuel - inventory.fuel = null - return + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): ChargerEntity { + return ChargerEntity( + manager, + this, + x, + y, + z, + world, + structureDirection, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + ) + } + + class ChargerEntity( + manager: MultiblockManager, + override val multiblock: ChargerMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + override var powerUnsafe: Int + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), UpdatedPowerDisplayEntity { + override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() + override val maxPower: Int = multiblock.maxPower + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + fun handleCharging(event: FurnaceBurnEvent, furnace: Furnace) { + val availablePower = getPower() + if (availablePower == 0) return + + val item = event.fuel + if (isPowerable(item)) { + handleLegacy(item, event, furnace, availablePower) + } + + val custom = item.customItem + + val custom = item.customItem ?: return + if (custom.hasComponent(CustomComponentTypes.POWER_STORAGE)) + handleModern(item, custom, custom.getComponent(CustomComponentTypes.POWER_STORAGE), event, furnace, inventory, sign, power) } - var multiplier = powerPerSecond - multiplier /= item.amount + fun handleModern( + item: ItemStack, + customItem: CustomItem, + powerManager: PowerStorage, + event: FurnaceBurnEvent, + furnace: Furnace, + inventory: FurnaceInventory, + sign: Sign, + power: Int + ) { + if (powerManager.getMaxPower(customItem, item) == powerManager.getPower(item)) { + val result = inventory.result + if (result != null && result.type != Material.AIR) return + inventory.result = event.fuel + inventory.fuel = null + return + } + + var multiplier = powerPerSecond + multiplier /= item.amount - if (item.amount * multiplier > power) return + if (item.amount * multiplier > power) return - powerManager.addPower(item, customItem, multiplier) + powerManager.addPower(item, customItem, multiplier) - PowerMachines.setPower(sign, power - multiplier * item.amount) + setPower(power - multiplier * item.amount) - furnace.cookTime = 20.toShort() - event.isCancelled = false + furnace.cookTime = 20.toShort() - val fuel = checkNotNull(inventory.fuel) + event.isCancelled = false + event.isBurning = false + event.burnTime = 20 + } - event.isBurning = false - event.burnTime = 20 + override fun onLoad() { + world.ion.multiblockManager.register(this) + + displayHandler.update() + } + + override fun handleRemoval() { + world.ion.multiblockManager.deregister(this) + + displayHandler.remove() + } + + override fun onUnload() { + world.ion.multiblockManager.deregister(this) + + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt index 6fc3bb98d6..bc20d45cee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt @@ -26,9 +26,7 @@ object FurnaceListener : SLEventListener() { val signBlock = state.block.getRelativeIfLoaded(directional.facing) ?: return val type = signBlock.type - if (!type.isWallSign) { - return - } + if (!type.isWallSign) return val sign = signBlock.getState(false) as Sign val checkStructure = false @@ -36,7 +34,7 @@ object FurnaceListener : SLEventListener() { val multiblock = MultiblockAccess.getMultiblock(sign, checkStructure, loadChunks) if (multiblock is FurnaceMultiblock) { - if (Multiblocks[sign, true, false] !== multiblock) { + if (!multiblock.signMatchesStructure(sign, loadChunks = false, particles = false)) { event.isCancelled = true return } From e9851e5c683d7f8d222f58b32e3f2f3a798c82cc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 9 Sep 2024 14:06:20 -0500 Subject: [PATCH 153/500] remove multiblock entities when signs pop off blocks --- .../server/features/multiblock/MultiblockAccess.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 426262b92c..7a1c0afb1a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -26,6 +26,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isSign +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -33,6 +34,7 @@ import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.block.Action import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPhysicsEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.inventory.EquipmentSlot @@ -291,4 +293,14 @@ object MultiblockAccess : IonServerComponent() { event.player.information("Destroyed ${removed.name}") } + + @EventHandler + fun onBlockPhysics(event: BlockPhysicsEvent) { + if (!event.changedType.isWallSign) return + val sign = event.block.state as? Sign ?: return + + val origin = MultiblockEntity.getOriginFromSign(sign) + + removeMultiblock(event.block.world, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) ?: return + } } From 39f86bac744db0693e39ca53bbfc4a775d2c8f7a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 9 Sep 2024 14:17:54 -0500 Subject: [PATCH 154/500] ... only if it results in the sign breaking --- .../ion/server/features/multiblock/MultiblockAccess.kt | 10 ++++++---- .../multiblock/type/power/charger/ChargerMultiblock.kt | 7 ------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 7a1c0afb1a..e732523104 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -25,11 +25,13 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isSign import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.block.data.type.WallSign import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.block.Action @@ -297,10 +299,10 @@ object MultiblockAccess : IonServerComponent() { @EventHandler fun onBlockPhysics(event: BlockPhysicsEvent) { if (!event.changedType.isWallSign) return - val sign = event.block.state as? Sign ?: return - - val origin = MultiblockEntity.getOriginFromSign(sign) + val data = event.changedBlockData as WallSign + val supportingBlock = event.block.getRelativeIfLoaded(data.facing.oppositeFace) ?: return + if (supportingBlock.type.isAir) return - removeMultiblock(event.block.world, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) ?: return + removeMultiblock(event.block.world, supportingBlock.x, supportingBlock.y, supportingBlock.z, data.facing.oppositeFace) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index f9cd76c9e5..3228a69127 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -16,7 +16,6 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material import org.bukkit.World @@ -163,20 +162,14 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere } override fun onLoad() { - world.ion.multiblockManager.register(this) - displayHandler.update() } override fun handleRemoval() { - world.ion.multiblockManager.deregister(this) - displayHandler.remove() } override fun onUnload() { - world.ion.multiblockManager.deregister(this) - displayHandler.remove() } From 1c96782b362ff81866cf10191cc8bb031ddb150c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 01:26:41 -0500 Subject: [PATCH 155/500] Remove the first attempt at transfer code --- .../transport/network/PowerNetwork.kt | 12 +--- .../features/transport/node/TransportNode.kt | 7 --- .../transport/node/general/JunctionNode.kt | 21 ++----- .../transport/node/general/LinearNode.kt | 21 ++----- .../node/power/InvertedDirectionalNode.kt | 20 +------ .../node/power/PowerDirectionalNode.kt | 20 +------ .../node/power/PowerEqualSplitterNode.kt | 39 +----------- .../node/power/PowerExtractorNode.kt | 54 +---------------- .../transport/node/power/PowerFlowMeter.kt | 21 +------ .../transport/node/power/PowerInputNode.kt | 41 +------------ .../transport/node/power/SolarPanelNode.kt | 50 +--------------- .../transport/node/type/DestinationNode.kt | 8 --- .../transport/node/type/SourceNode.kt | 16 ----- .../transport/node/type/StepHandler.kt | 19 ------ .../server/features/transport/step/Step.kt | 31 ---------- .../transport/step/head/BranchHead.kt | 23 ------- .../transport/step/head/HeadHolder.kt | 10 ---- .../transport/step/head/MultiBranchHead.kt | 41 ------------- .../transport/step/head/SingleBranchHead.kt | 16 ----- .../transport/step/head/gas/GasBranchHead.kt | 5 -- .../step/head/gas/MultiGasBranchHead.kt | 18 ------ .../step/head/gas/SingleGasBranchHead.kt | 56 ----------------- .../step/head/power/MultiPowerBranchHead.kt | 18 ------ .../step/head/power/PowerBranchHead.kt | 5 -- .../step/head/power/SinglePowerBranchHead.kt | 56 ----------------- .../transport/step/origin/StepOrigin.kt | 6 -- .../step/origin/gas/ExtractedGasOrigin.kt | 9 --- .../step/origin/power/ExtractorPowerOrigin.kt | 60 ------------------- .../step/origin/power/PowerOrigin.kt | 9 --- .../step/origin/power/SolarPowerOrigin.kt | 18 ------ .../transport/step/result/ChangeHead.kt | 12 ---- .../transport/step/result/EndBranch.kt | 11 ---- .../transport/step/result/MoveForward.kt | 45 -------------- .../transport/step/result/StepResult.kt | 9 --- 34 files changed, 23 insertions(+), 784 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/GasBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt index c29d412e81..f9df2bab00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.network import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType @@ -13,7 +12,6 @@ import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap @@ -32,19 +30,13 @@ class PowerNetwork(holder: NetworkHolder) : TransportNetwork(holde private suspend fun tickSolarPanels() { for (solarPanel in solarPanels) { - runCatching { solarPanel.startStep()?.invoke() }.onFailure { - IonServer.slF4JLogger.error("Exception ticking solar panel! $it") - it.printStackTrace() - } + } } private suspend fun tickExtractors() { extractors.forEach { (key, extractor) -> - runCatching { extractor.startStep()?.invoke() }.onFailure { - IonServer.slF4JLogger.error("Exception ticking extractor at ${toVec3i(key)}! $it") - it.printStackTrace() - } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 44b236a62e..eaef8a43ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -2,8 +2,6 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.step.head.BranchHead import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -104,11 +102,6 @@ interface TransportNode : PDCSerializable, destination: PowerInputNode, transferred: Int) {} - companion object : PersistentDataType { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 2e7eb5332c..ba4e8fa26b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -5,25 +5,21 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -abstract class JunctionNode, B: JunctionNode>(override val network: T) : MultiNode, StepHandler { +abstract class JunctionNode, B: JunctionNode>(override val network: T) : MultiNode { override var isDead: Boolean = false override val positions: MutableSet = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> + return node !is PowerExtractorNode && node !is SolarPanelNode } override fun loadData(persistentDataContainer: PersistentDataContainer) { @@ -49,13 +45,4 @@ abstract class JunctionNode, B: Ju network.nodes[it]?.buildRelations(it) } } - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .firstOrNull() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index cfc34b79bd..65c930c647 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -6,41 +6,28 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Axis -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -abstract class LinearNode, B: LinearNode>(override val network: T) : MultiNode, StepHandler { +abstract class LinearNode, B: LinearNode>(override val network: T) : MultiNode { override var isDead: Boolean = false override val positions: MutableSet = LongOpenHashSet() override val relationships: MutableSet = ObjectOpenHashSet() var axis by Delegates.notNull() override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> + return node !is PowerExtractorNode && node !is SolarPanelNode } - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .firstOrNull() - abstract suspend fun addBack(position: BlockKey) override suspend fun rebuildNode(position: BlockKey) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index 7eb6bfd8a3..a500d83591 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -5,19 +5,13 @@ import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class InvertedDirectionalNode(override val network: PowerNetwork) : SingleNode, StepHandler { +class InvertedDirectionalNode(override val network: PowerNetwork) : SingleNode { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() @@ -28,17 +22,7 @@ class InvertedDirectionalNode(override val network: PowerNetwork) : SingleNode, override fun isTransferableTo(node: TransportNode): Boolean { if (node is EndRodNode) return false - return node !is SourceNode<*> - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .randomOrNull() - - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() + return node !is PowerExtractorNode && node !is SolarPanelNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index bb6257c1f7..e73dced21c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -6,20 +6,14 @@ import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerDirectionalNode(override val network: PowerNetwork) : SingleNode, StepHandler { +class PowerDirectionalNode(override val network: PowerNetwork) : SingleNode { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() private var variant: Material by Delegates.notNull() @@ -32,17 +26,7 @@ class PowerDirectionalNode(override val network: PowerNetwork) : SingleNode, Ste override fun isTransferableTo(node: TransportNode): Boolean { if (node is SpongeNode) return false - return node !is SourceNode<*> - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .randomOrNull() - - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() + return node !is PowerExtractorNode && node !is SolarPanelNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index a0a21b78b3..ed1d02423c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -5,22 +5,13 @@ import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.head.power.MultiPowerBranchHead -import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.result.ChangeHead -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerEqualSplitterNode(override val network: PowerNetwork) : SingleNode, StepHandler { +class PowerEqualSplitterNode(override val network: PowerNetwork) : SingleNode { override var isDead: Boolean = false override var position: BlockKey by Delegates.notNull() override val relationships: MutableSet = ObjectOpenHashSet() @@ -30,33 +21,7 @@ class PowerEqualSplitterNode(override val network: PowerNetwork) : SingleNode, S } override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .randomOrNull() - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - val transferable = getTransferableNodes() - - val newHeads = transferable.mapTo(mutableSetOf()) { neighbor -> - MultiBranchHead.MultiHeadHolder { - SinglePowerBranchHead( - holder = it, - lastDirection = neighbor.second, - currentNode = this@PowerEqualSplitterNode, - share = 1.0 - ) - } - } - - return ChangeHead(MultiPowerBranchHead( - holder = head.holder, - 1.0 / transferable.size, - previousNodes = head.previousNodes, - heads = newHeads - )) + return node !is PowerExtractorNode && node !is SolarPanelNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 2713cbd683..686d118e02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -6,25 +6,16 @@ import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin -import net.horizonsend.ion.server.features.transport.step.origin.power.ExtractorPowerOrigin -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt import kotlin.properties.Delegates -class PowerExtractorNode(override val network: PowerNetwork) : SingleNode, SourceNode { +class PowerExtractorNode(override val network: PowerNetwork) : SingleNode { constructor(network: PowerNetwork, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this @@ -46,43 +37,7 @@ class PowerExtractorNode(override val network: PowerNetwork) : SingleNode, Sourc */ override fun isTransferableTo(node: TransportNode): Boolean { if (node is PowerInputNode) return false - return node !is SourceNode<*> - } - - /* - * Nothing unique with how pathfinding is done, simply move onto a random transferable neighbor that isn't a dead end - */ - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { - return getTransferableNodes() - .filter { it.first.getTransferableNodes().isNotEmpty() } - .randomOrNull() - } - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - return MoveForward() - } - - override suspend fun startStep(): Step? { - if (extractableNodes.isEmpty()) return null - - val extractablePowerPool = extractableNodes.flatMap { it.getPoweredMultiblocks() } - if (extractablePowerPool.all { it.isEmpty() }) return null - - val step = Step( - network = this.network, - origin = getOriginData() ?: return null - ) { - SinglePowerBranchHead( - holder = this, - lastDirection = BlockFace.SELF, - currentNode = this@PowerExtractorNode, - share = 1.0, - ) - } - - markTicked() - - return step + return node !is PowerExtractorNode && node !is SolarPanelNode } private var lastTicked: Long = System.currentTimeMillis() @@ -90,11 +45,6 @@ class PowerExtractorNode(override val network: PowerNetwork) : SingleNode, Sourc lastTicked = System.currentTimeMillis() } - override suspend fun getOriginData(): StepOrigin? { - if (getTransferableNodes().isEmpty()) return null - return ExtractorPowerOrigin(this) - } - fun getTransferPower(): Int { val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 0997785c60..4e6a0ca8c9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -12,12 +12,6 @@ import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -32,7 +26,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandler { +class PowerFlowMeter(override val network: PowerNetwork) : SingleNode { constructor(network: PowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction @@ -49,22 +43,13 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode, StepHandl * And it cannot transfer into a source */ override fun isTransferableTo(node: TransportNode): Boolean { - return node !is SourceNode<*> + return node !is PowerExtractorNode && node !is SolarPanelNode } - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() - } - - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? = getTransferableNodes() - .filterNot { head.previousNodes.contains(it.first) } - .randomOrNull() - private val STORED_AVERAGES = 20 private val averages = mutableListOf() - override suspend fun onCompleteChain(final: BranchHead<*>, destination: PowerInputNode, transferred: Int) { + fun onCompleteChain(transferred: Int) { addTransferred(TransferredPower(transferred, System.currentTimeMillis())) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index beac55562b..f2bbdf9e24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,19 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.power import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.command.admin.debug -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.network.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.network.holders.ShipNetworkHolder import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.DestinationNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.origin.power.ExtractorPowerOrigin -import net.horizonsend.ion.server.features.transport.step.origin.power.PowerOrigin import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -21,12 +15,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerInputNode(override val network: PowerNetwork) : SingleNode, DestinationNode { +class PowerInputNode(override val network: PowerNetwork) : SingleNode { constructor(network: PowerNetwork, position: BlockKey) : this(network) { this.position = position } @@ -67,38 +60,6 @@ class PowerInputNode(override val network: PowerNetwork) : SingleNode, Destinati } } - override suspend fun finishChain(head: BranchHead) { - val origin = head.holder.getOrigin() - - head.markDead() - - val multis = getPoweredMultiblocks() - - val destinationMultiblock = multis - .filter { it as MultiblockEntity; !it.removed } - .randomOrNull() ?: return // println("No multis! origin: $origin") - - val power: Int = when (origin) { - is PowerOrigin -> origin.getTransferPower(destinationMultiblock) - else -> throw NotImplementedError("Unknown power origin $origin") - } - - val remainder = if (origin is ExtractorPowerOrigin) origin.removeOrigin(power) else 0 - val toAdd = power - remainder - destinationMultiblock.addPower(toAdd) - - debugAudience.debug(""" - Power endpoint reached! - Origin $origin - $remainder could not be removed - Added $toAdd to $destinationMultiblock - """.trimIndent()) - - head.previousNodes.forEach { - it.onCompleteChain(head, this, power) - } - } - override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index c96c45bfa0..d0223edb5a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -5,14 +5,6 @@ import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeRelationship import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.head.power.SinglePowerBranchHead -import net.horizonsend.ion.server.features.transport.step.origin.power.SolarPowerOrigin -import net.horizonsend.ion.server.features.transport.step.result.MoveForward -import net.horizonsend.ion.server.features.transport.step.result.StepResult import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS @@ -26,9 +18,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.GameRule import org.bukkit.Material import org.bukkit.World -import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN -import org.bukkit.block.BlockFace.SELF import org.bukkit.block.BlockFace.UP import org.bukkit.block.data.AnaloguePowerable import org.bukkit.persistence.PersistentDataContainer @@ -41,9 +31,7 @@ import java.util.function.Consumer **/ class SolarPanelNode( override val network: PowerNetwork -) : MultiNode, - SourceNode, - StepHandler { +) : MultiNode { override var isDead: Boolean = false override val positions: MutableSet = ConcurrentHashMap.newKeySet() override val relationships: MutableSet = ConcurrentHashMap.newKeySet() @@ -62,48 +50,12 @@ class SolarPanelNode( return node !is PowerExtractorNode } - override suspend fun startStep(): Step? { - val power = getPower() - if (power <= 0) return null - - return Step( - network = this.network, - origin = getOriginData() - ) { - SinglePowerBranchHead( - holder = this, - lastDirection = SELF, - currentNode = this@SolarPanelNode, - share = 1.0, - ) - } - } - - override suspend fun handleHeadStep(head: SingleBranchHead): StepResult { - // Simply move on to the next node - return MoveForward() - } - - override suspend fun getOriginData(): SolarPowerOrigin = SolarPowerOrigin(this) - /** * The distance this solar node is from the nearest exit of the solar field * This value will be -1 if there are no exits present **/ private var exitDistance: Int = 0 - override suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? { - val neighbors = getTransferableNodes() - return neighbors.shuffled().firstOrNull { it.first !is SolarPanelNode } ?: - neighbors - .filter { - val node = it.first - node is SolarPanelNode && node.exitDistance < this.exitDistance - } // Make sure it can't move further from an exit - .shuffled() // Make sure the lowest priority, if multiple is random every time - .minByOrNull { (it.first as SolarPanelNode).exitDistance } - } - /** * Calculate the distance to an exit of a solar field * This method is run upon neighbor unloads diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt deleted file mode 100644 index 472e6579cf..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/DestinationNode.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.BranchHead - -interface DestinationNode { - suspend fun finishChain(head: BranchHead) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt deleted file mode 100644 index fa5ecf7ee8..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SourceNode.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.Step -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -/** - * Representing the start of a power system - * - * Nodes may not transfer into a source node - **/ -interface SourceNode : StepHandler { - suspend fun getOriginData(): StepOrigin? - - suspend fun startStep(): Step? -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt deleted file mode 100644 index 6fd56d57a2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/StepHandler.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import net.horizonsend.ion.server.features.transport.step.result.StepResult -import org.bukkit.block.BlockFace - -interface StepHandler { - /** - * Handle the stepping of power through this node - * - * This may create a new step for a single node, spawn off multiple steps, or more - * Each node defines how it is stepped. - **/ - suspend fun handleHeadStep(head: SingleBranchHead): StepResult - - suspend fun getNextNode(head: SingleBranchHead, entranceDirection: BlockFace): Pair? -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt deleted file mode 100644 index 25ba9a7832..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/Step.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -class Step private constructor( - val network: T, - private val stepOrigin: StepOrigin, -) : HeadHolder { - override lateinit var head: BranchHead - - constructor(network: T, origin: StepOrigin, getHead: Step.() -> BranchHead) : this(network, origin) { - this.head = getHead() - } - - constructor(network: T, origin: StepOrigin, head: BranchHead) : this(network, origin) { - this.head = head - } - - suspend operator fun invoke() { - while (!head.isDead()) { - head.stepForward() - } - } - - override fun getOrigin(): StepOrigin { - return stepOrigin - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt deleted file mode 100644 index 10fe3ec629..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/BranchHead.kt +++ /dev/null @@ -1,23 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode - -interface BranchHead { - val holder: HeadHolder - - /** Nodes that this head has covered */ - val previousNodes: MutableSet - - /** - * Moves this step forward - * If the head is to be replaced with a new one, return that. - **/ - suspend fun stepForward() - - /** Returns whether this head is dead */ - fun isDead(): Boolean - - /** Sets this branch to be dead */ - fun markDead() -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt deleted file mode 100644 index 37f8162f45..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/HeadHolder.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -interface HeadHolder { - var head: BranchHead - - fun getOrigin(): StepOrigin -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt deleted file mode 100644 index 9d49492f23..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/MultiBranchHead.kt +++ /dev/null @@ -1,41 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin -import kotlin.properties.Delegates - -/** A head which branches into multiple sub-heads */ -interface MultiBranchHead : BranchHead { - val heads: MutableSet> - - /** Holder that allows the head within to be replaced */ - class MultiHeadHolder() : HeadHolder { - override var head: BranchHead by Delegates.notNull() - - constructor(head: BranchHead) : this() { - this.head = head - } - - constructor(constructHead: (MultiHeadHolder) -> BranchHead) : this() { - this.head = constructHead.invoke(this) - } - - override fun getOrigin(): StepOrigin { - return head.holder.getOrigin() - } - } - - // Just pass it forward - override suspend fun stepForward() { - heads.forEach { it.head.stepForward() } - } - - // Just pass it forward - override fun isDead(): Boolean { - return heads.all { it.head.isDead() } - } - - override fun markDead() { - heads.forEach { it.head.markDead() } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt deleted file mode 100644 index 5eaf92df4a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/SingleBranchHead.kt +++ /dev/null @@ -1,16 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import org.bukkit.block.BlockFace - -/** - * Can either branch off of a MultiBranch or exist alone - **/ -interface SingleBranchHead : BranchHead { - /** The last offset this branch moved */ - var lastDirection: BlockFace - - /** The current location of the tip of the branch */ - var currentNode: TransportNode -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/GasBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/GasBranchHead.kt deleted file mode 100644 index a9455bbd83..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/GasBranchHead.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.gas - -interface GasBranchHead { - val share: Double -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt deleted file mode 100644 index c16567ec77..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/MultiGasBranchHead.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.gas - -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead - -/** - * - * - **/ -class MultiGasBranchHead( - override val holder: HeadHolder, - override val share: Double, - override val previousNodes: MutableSet = mutableSetOf(), - override val heads: MutableSet> = mutableSetOf(), -) : MultiBranchHead, GasBranchHead - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt deleted file mode 100644 index 7e814d0ab4..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/gas/SingleGasBranchHead.kt +++ /dev/null @@ -1,56 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.gas - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork as ChunkTransportNetwork1 -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.DestinationNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import org.bukkit.block.BlockFace - -/** - * Transferred power down a single path. - * - * - **/ -class SingleGasBranchHead( - override val holder: HeadHolder, - override var lastDirection: BlockFace, - override var currentNode: TransportNode, - override val share: Double, - override val previousNodes: MutableSet = mutableSetOf() -) : SingleBranchHead, GasBranchHead { - private var isDead = false - - override fun markDead() { - isDead = true - } - - override fun isDead(): Boolean = isDead - - @Suppress("UNCHECKED_CAST") - override suspend fun stepForward() { - val node = currentNode - - if (tryCast>(node) { finishChain(this@SingleGasBranchHead) }) return - - // All other nodes handle steps transferring in / out - node as StepHandler - - val result = node.handleHeadStep(this as SingleBranchHead) - - result.apply(holder as HeadHolder) - } - - // Get around runtime type erasure - private inline fun tryCast(instance: Any?, block: T.() -> Unit): Boolean { - if (instance is T) { - block(instance) - return true - } - - return false - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt deleted file mode 100644 index 946ac1280b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/MultiPowerBranchHead.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.power - -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead - -/** - * - * - **/ -class MultiPowerBranchHead( - override val holder: HeadHolder, - override val share: Double, - override val previousNodes: MutableSet = mutableSetOf(), - override val heads: MutableSet> = mutableSetOf(), -) : MultiBranchHead, PowerBranchHead - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt deleted file mode 100644 index 4af2a1afff..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/PowerBranchHead.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.power - -interface PowerBranchHead { - val share: Double -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt deleted file mode 100644 index ceae3a6116..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/head/power/SinglePowerBranchHead.kt +++ /dev/null @@ -1,56 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.head.power - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork as ChunkTransportNetwork1 -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.DestinationNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead -import org.bukkit.block.BlockFace - -/** - * Transferred power down a single path. - * - * - **/ -class SinglePowerBranchHead( - override val holder: HeadHolder, - override var lastDirection: BlockFace, - override var currentNode: TransportNode, - override val share: Double, - override val previousNodes: MutableSet = mutableSetOf() -) : SingleBranchHead, PowerBranchHead { - private var isDead = false - - override fun markDead() { - isDead = true - } - - override fun isDead(): Boolean = isDead - - @Suppress("UNCHECKED_CAST") - override suspend fun stepForward() { - val node = currentNode - - if (tryCast>(node) { finishChain(this@SinglePowerBranchHead) }) return - - // All other nodes handle steps transferring in / out - node as StepHandler - - val result = node.handleHeadStep(this as SingleBranchHead) - - result.apply(holder as HeadHolder) - } - - // Get around runtime type erasure - private inline fun tryCast(instance: Any?, block: T.() -> Unit): Boolean { - if (instance is T) { - block(instance) - return true - } - - return false - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt deleted file mode 100644 index 098eef4dc1..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/StepOrigin.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.origin - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork - -interface StepOrigin - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt deleted file mode 100644 index 1c1e348444..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/gas/ExtractedGasOrigin.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.origin.gas - -import net.horizonsend.ion.server.features.transport.network.FluidNetwork -import net.horizonsend.ion.server.features.transport.node.gas.FluidExtractorNode -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -class ExtractedGasOrigin( - val extractorNode: FluidExtractorNode -) : StepOrigin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt deleted file mode 100644 index bde2dfc276..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/ExtractorPowerOrigin.kt +++ /dev/null @@ -1,60 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.origin.power - -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -class ExtractorPowerOrigin( - val extractorNode: PowerExtractorNode -) : StepOrigin, PowerOrigin { - override val transferLimit: Int = extractorNode.getTransferPower() - /** - * Remove power from the origin extractor's multiblocks. - * - * @return the amount of power that could not be removed - **/ - fun removeOrigin(amount: Int): Int { - // List of multiblock entities that power may be taken from - val availableEntities = extractorNode.extractableNodes - .flatMap { it.getPoweredMultiblocks() } - .distinct() - .filterNotTo(mutableListOf()) { (it as MultiblockEntity).removed || it.isEmpty() } - - val minRemove = minOf(amount, availableEntities.minOfOrNull { it.getPower() } ?: return amount) - - val share = minRemove / availableEntities.size - - var removeRemaining = minRemove - - // Remove an equal share from each of the inventories - for (entity in availableEntities) { - entity as MultiblockEntity - if (entity.removed) continue - - // Should never be more than 0, but handle the possibility - val notRemoved = entity.removePower(share) - removeRemaining -= (share - notRemoved) - } - - availableEntities.firstOrNull { it.canRemovePower(removeRemaining) }?.run { - removePower(removeRemaining) - removeRemaining = 0 - } - - return removeRemaining - } - - private fun getAvailablePower(): Int = extractorNode.extractableNodes - .flatMap { it.getPoweredMultiblocks() } - .distinct() - .filterNot { (it as MultiblockEntity).removed } - .sumOf { it.getPower() } - - override fun getTransferPower(destination: PoweredMultiblockEntity): Int { - val destinationCapacity = destination.maxPower - destination.getPower() - - return minOf(destinationCapacity, transferLimit, getAvailablePower()) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt deleted file mode 100644 index 82f8025e2a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/PowerOrigin.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.origin.power - -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity - -interface PowerOrigin { - fun getTransferPower(destination: PoweredMultiblockEntity): Int - - val transferLimit: Int -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt deleted file mode 100644 index fe330e016c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/origin/power/SolarPowerOrigin.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.origin.power - -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.step.origin.StepOrigin - -class SolarPowerOrigin(val origin: SolarPanelNode) : StepOrigin, PowerOrigin { - override val transferLimit: Int = Int.MAX_VALUE - private val powerTransfer = origin.tickAndGetPower() - - override fun getTransferPower(destination: PoweredMultiblockEntity): Int { - val destinationCapacity = destination.maxPower - destination.getPower() - - // No max transfer limit for solar fields, as large ones would quickly overwhelm any limit - return minOf(powerTransfer, destinationCapacity) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt deleted file mode 100644 index 2de3cceec0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/ChangeHead.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.result - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.BranchHead -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder - -/** A result which changes the head of the step to a new one */ -class ChangeHead(val new: BranchHead) : StepResult { - override suspend fun apply(headHolder: HeadHolder) { - headHolder.head = new - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt deleted file mode 100644 index 6fd6f9804a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/EndBranch.kt +++ /dev/null @@ -1,11 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.result - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder - -/** A result which marks the branch as dead */ -class EndBranch : StepResult { - override suspend fun apply(headHolder: HeadHolder) { - headHolder.head.markDead() - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt deleted file mode 100644 index 1534339d9a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/MoveForward.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.result - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.type.DestinationNode -import net.horizonsend.ion.server.features.transport.node.type.SourceNode -import net.horizonsend.ion.server.features.transport.node.type.StepHandler -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder -import net.horizonsend.ion.server.features.transport.step.head.MultiBranchHead -import net.horizonsend.ion.server.features.transport.step.head.SingleBranchHead - -/** A result which moves the head of the branch forward, using the current node's pathfinding */ -class MoveForward() : StepResult { - override suspend fun apply(headHolder: HeadHolder) { - val branchHead = headHolder.head - - if (branchHead is MultiBranchHead<*>) throw IllegalArgumentException("Multi branches can't be modified!") - - val currentNode = (branchHead as SingleBranchHead).currentNode - - // If the next node is a step handler, - tryCast>(currentNode) { - val (next, offset) = this.getNextNode(branchHead, branchHead.lastDirection) ?: return EndBranch().apply(headHolder) - - branchHead.previousNodes.add(branchHead.currentNode) - branchHead.currentNode = next - branchHead.lastDirection = offset - } - - tryCast>(currentNode) { - finishChain(headHolder.head) - } - - if (branchHead is SourceNode<*>) throw NotImplementedError() - } - - // Get around runtime type erasure - private inline fun tryCast(instance: Any?, block: T.() -> Unit): Boolean { - if (instance is T) { - block(instance) - return true - } - - return false - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt deleted file mode 100644 index f8883b5ab1..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/step/result/StepResult.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.transport.step.result - -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.step.head.HeadHolder - -interface StepResult { - suspend fun apply(headHolder: HeadHolder) -} - From def21ed077571f50315114ceb324ded32010a15e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 17:32:59 -0500 Subject: [PATCH 156/500] Half functioning new system, need to iron out some grid problems --- .../server/command/admin/IonChunkCommand.kt | 9 +- .../ion/server/command/admin/WorldCommand.kt | 22 ++++ .../entity/type/fluids/FluidStoringEntity.kt | 71 +++++++++++- .../type/fluids/storage/InternalStorage.kt | 2 +- .../type/power/PoweredMultiblockEntity.kt | 67 ++++++++++- .../manager/ChunkMultiblockManager.kt | 4 +- .../multiblock/manager/MultiblockManager.kt | 8 +- .../manager/ShipMultiblockManager.kt | 4 +- .../defense/passive/areashield/AreaShield.kt | 1 + .../type/fluid/ElectrolysisMultiblock.kt | 9 ++ .../collector/PipedGasCollectorMultiblock.kt | 3 + .../fluid/storage/FluidStorageMultiblock.kt | 5 +- .../type/power/charger/ChargerMultiblock.kt | 3 + .../type/power/storage/PowerBankMultiblock.kt | 3 + .../ion/server/features/starship/Starship.kt | 2 +- .../transport/ChunkTransportManager.kt | 36 +++--- .../features/transport/IonUpdateExtent.kt | 10 +- .../features/transport/TransportManager.kt | 7 +- .../features/transport/grid/FluidGrid.kt | 18 +++ .../server/features/transport/grid/Grid.kt | 106 ++++++++++++++++++ .../features/transport/grid/GridType.kt | 17 +++ .../features/transport/grid/PowerGrid.kt | 18 +++ .../transport/grid/WorldGridManager.kt | 104 +++++++++++++++++ .../features/transport/grid/util/GraphUtil.kt | 45 ++++++++ .../features/transport/grid/util/Sink.kt | 5 + .../features/transport/grid/util/Source.kt | 5 + .../features/transport/node/NodeFactory.kt | 8 +- .../features/transport/node/NodeType.kt | 4 +- .../features/transport/node/NodeUtils.kt | 18 +-- .../features/transport/node/TransportNode.kt | 48 +++++--- .../node/fluid/FluidExtractorNode.kt | 4 + .../transport/node/fluid/FluidInputNode.kt | 35 ++++++ .../node/{gas => fluid}/FluidNodeFactory.kt | 32 +++--- .../node/fluid/GasDirectionalNode.kt | 4 + .../transport/node/fluid/GasFilterNode.kt | 4 + .../transport/node/fluid/GasFlowMeter.kt | 4 + .../node/fluid/GasInvertedDirectionalNode.kt | 4 + .../transport/node/fluid/GasJunctionNode.kt | 24 ++++ .../transport/node/fluid/GasValveNode.kt | 4 + .../transport/node/fluid/LightningRodNode.kt | 24 ++++ .../transport/node/gas/FluidExtractorNode.kt | 4 - .../transport/node/gas/GasDirectionalNode.kt | 4 - .../transport/node/gas/GasFilterNode.kt | 4 - .../transport/node/gas/GasFlowMeter.kt | 4 - .../transport/node/gas/GasInputNode.kt | 4 - .../node/gas/GasInvertedDirectionalNode.kt | 4 - .../transport/node/gas/GasJunctionNode.kt | 23 ---- .../transport/node/gas/GasValveNode.kt | 4 - .../transport/node/gas/LightningRodNode.kt | 23 ---- .../transport/node/general/JunctionNode.kt | 28 +---- .../transport/node/general/LinearNode.kt | 27 +---- .../manager/FluidNodeManager.kt} | 14 +-- .../manager/NodeManager.kt} | 58 ++++------ .../manager/PowerNodeManager.kt} | 23 +--- .../manager}/ShipTransportManager.kt | 2 +- .../manager}/holders/ChunkNetworkHolder.kt | 13 +-- .../manager}/holders/NetworkHolder.kt | 6 +- .../manager}/holders/ShipNetworkHolder.kt | 6 +- .../transport/node/power/EndRodNode.kt | 11 +- .../node/power/InvertedDirectionalNode.kt | 14 +-- .../node/power/PowerDirectionalNode.kt | 12 +- .../node/power/PowerEqualSplitterNode.kt | 14 +-- .../node/power/PowerExtractorNode.kt | 26 ++--- .../transport/node/power/PowerFlowMeter.kt | 17 +-- .../transport/node/power/PowerInputNode.kt | 68 ++--------- .../transport/node/power/PowerNodeFactory.kt | 30 ++--- .../transport/node/power/SolarPanelNode.kt | 63 +++++------ .../transport/node/power/SpongeNode.kt | 12 +- .../features/transport/node/type/MultiNode.kt | 43 +++++-- .../transport/node/type/SingleNode.kt | 14 ++- .../ion/server/features/world/IonWorld.kt | 4 + .../features/world/chunk/ChunkRegion.kt | 1 - 72 files changed, 890 insertions(+), 491 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidExtractorNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{gas => fluid}/FluidNodeFactory.kt (71%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{network/FluidNetwork.kt => node/manager/FluidNodeManager.kt} (61%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{network/TransportNetwork.kt => node/manager/NodeManager.kt} (66%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{network/PowerNetwork.kt => node/manager/PowerNodeManager.kt} (79%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => node/manager}/ShipTransportManager.kt (81%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{network => node/manager}/holders/ChunkNetworkHolder.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{network => node/manager}/holders/NetworkHolder.kt (80%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{network => node/manager}/holders/ShipNetworkHolder.kt (84%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 88f97d5f31..c491b507e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -12,9 +12,8 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -90,7 +89,7 @@ object IonChunkCommand : SLCommand() { sender.information("${grid.nodes.values.distinct().size} unique node(s).") when (grid) { - is PowerNetwork -> { + is PowerNodeManager -> { sender.information("${grid.solarPanels.size} solar panels") sender.information("${grid.extractors.size} extractors") sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") @@ -116,7 +115,7 @@ object IonChunkCommand : SLCommand() { grid.nodes.clear() when (grid) { - is PowerNetwork -> { + is PowerNodeManager -> { grid.extractors.clear() grid.solarPanels.clear() } @@ -125,7 +124,7 @@ object IonChunkCommand : SLCommand() { for (x in ionChunk.originX ..ionChunk.originX + 15) { for (z in ionChunk.originZ..ionChunk.originZ + 15) { for (y in ionChunk.world.minHeight until ionChunk.world.maxHeight) { - grid.createNodeFromBlock(getBlockSnapshotAsync(sender.world, x, y, z)!!) + grid.createNodeFromBlock(sender.world.getBlockAt(x, y, z)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt index e8a4862486..5440af2319 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_LIGHT_GRAY import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.common.utils.text.formatSpacePrefix +import net.horizonsend.ion.common.utils.text.join import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.command.SLCommand @@ -21,6 +22,7 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.features.world.environment.Environment import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent @@ -214,4 +216,24 @@ object WorldCommand : SLCommand() { sender.information("Entities:") sender.sendMessage(menu) } + + @Subcommand("query grids") + fun onQueryGrids(sender: Player, @Optional page: Int?) { + val manager = sender.world.ion.gridManager + val grids = manager.allGrids.toList() + + val menu = formatPaginatedMenu( + grids.size, + "/onQueryEntities", + page ?: 1 + ) { + val grid = grids[it] + + ofChildren(text(grid.javaClass.simpleName), space(), bracketed(text("${grid.manager.world.world.name}: grid, ${grid.nodes.size} nodes"))) + .hoverEvent(grid.nodes.map { node -> node.toComponent() }.join(newline())) + } + + sender.information("Grids:") + sender.sendMessage(menu) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index d29579389f..5246b95212 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -1,17 +1,26 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.grid.FluidGrid +import net.horizonsend.ion.server.features.transport.grid.util.Sink +import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.kyori.adventure.text.Component import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER -interface FluidStoringEntity { +interface FluidStoringEntity : Source, Sink { val capacities: Array /** @@ -62,7 +71,6 @@ interface FluidStoringEntity { fun getStorage(key: NamespacedKey): StorageContainer = capacities.first { it.namespacedKey == key } - fun storeFluidData(destination: PersistentDataContainer, context: PersistentDataAdapterContext) { val storages = context.newPersistentDataContainer() @@ -96,4 +104,63 @@ interface FluidStoringEntity { internalStorage ) } + + val fluidInputOffset: Vec3i + + fun getFluidInputLocation(): Vec3i { + this as MultiblockEntity + return getRelative( + origin = vec3i, + forwardFace= structureDirection, + right = fluidInputOffset.x, + up = fluidInputOffset.y, + forward = fluidInputOffset.z + ) + } + + fun getFluidInputNode(): FluidInputNode? { + this as MultiblockEntity + val block = getFluidInputLocation() + + val chunk = IonChunk[world, block.x.shr(4), block.z.shr(4)] ?: return null + val manager = chunk.transportNetwork.powerNodeManager + val node = manager.getInternalNode(toBlockKey(block)) + + if (node != null) return node as? FluidInputNode + + // Try to place unregistered node + manager.manager.processBlockAddition(world.getBlockAt(block.x, block.y, block.z)) + return manager.getInternalNode(toBlockKey(block)) as? FluidInputNode + } + + fun bindFluidInput() { + val existing = getFluidInputNode() ?: return + if (existing.boundMultiblockEntity != null) return + + existing.boundMultiblockEntity = this + } + + fun releaseFluidInput() { + val existing = getFluidInputNode() ?: return + if (existing.boundMultiblockEntity != this) return + + existing.boundMultiblockEntity = null + } + + /** + * Returns the grid that this multiblock is tied to + * + * Should only return null if the multiblock is partially unloaded, or not intact. + **/ + fun getFluidGrid(): FluidGrid? { + return getFluidInputNode()?.grid as? FluidGrid + } + + override fun isProviding(): Boolean { + return getStoredResources().entries.any { it.key != null && it.value > 0 } + } + + override fun isRequesting(): Boolean { + return capacities.any { it.storage.getAmount() < it.storage.getCapacity() } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt index 425a0ba9fe..1418589a1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt @@ -119,7 +119,7 @@ abstract class InternalStorage { /** Notify update handlers of an update */ fun runUpdates() { - updateHandlers.forEach { it.invoke(this) } + updateHandlers.toList().forEach { it.invoke(this) } } override fun toString(): String { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index d298d86f48..154c7b1ba2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,16 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.transport.grid.PowerGrid +import net.horizonsend.ion.server.features.transport.grid.util.Sink +import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.persistence.PersistentDataType -interface PoweredMultiblockEntity { +interface PoweredMultiblockEntity: Sink { val position: BlockKey var powerUnsafe: Int val maxPower: Int @@ -78,4 +86,61 @@ interface PoweredMultiblockEntity { fun updatePowerVisually() fun formatPower(): Component = ofChildren(prefixComponent, text(powerUnsafe, GREEN)) + + val powerInputOffset: Vec3i + + fun getRealInputLocation(): Vec3i { + this as MultiblockEntity + return getRelative( + origin = vec3i, + forwardFace= structureDirection, + right = powerInputOffset.x, + up = powerInputOffset.y, + forward = powerInputOffset.z + ) + } + + fun getInputNode(): PowerInputNode? { + this as MultiblockEntity + val block = getRealInputLocation() + + val chunk = IonChunk[world, block.x.shr(4), block.z.shr(4)] ?: return null + val manager = chunk.transportNetwork.powerNodeManager + val node = manager.getInternalNode(toBlockKey(block)) + + if (node != null) return node as? PowerInputNode + + // Try to place unregistered node + manager.manager.processBlockAddition(world.getBlockAt(block.x, block.y, block.z)) + return manager.getInternalNode(toBlockKey(block)) as? PowerInputNode + } + + fun bindInputNode() { + val existing = getInputNode() ?: return + if (existing.boundMultiblockEntity != null) return + + existing.boundMultiblockEntity = this + existing.grid.registerSink(this) + } + + fun releaseInputNode() { + val existing = getInputNode() ?: return + if (existing.boundMultiblockEntity != this) return + + existing.boundMultiblockEntity = null + existing.grid.removeSink(this) + } + + /** + * Returns the grid that this multiblock is tied to + * + * Should only return null if the multiblock is partially unloaded, or not intact. + **/ + fun getGrid(): PowerGrid? { + return getInputNode()?.grid as? PowerGrid + } + + override fun isRequesting(): Boolean { + return getPower() < maxPower + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 11224de786..fa9c00274f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -4,8 +4,8 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD @@ -24,7 +24,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) } - override fun getNetwork(type: NetworkType): TransportNetwork { + override fun getNetwork(type: NetworkType): NodeManager { return type.get(chunk) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 8810c65e6b..a2eb9db767 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -9,9 +9,9 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -43,7 +43,7 @@ abstract class MultiblockManager(val log: Logger) { fun getAllMultiblockEntities() = multiblockEntities - abstract fun getNetwork(type: NetworkType): TransportNetwork + abstract fun getNetwork(type: NetworkType): NodeManager /** * Handles the addition of a multiblock entity @@ -125,7 +125,7 @@ abstract class MultiblockManager(val log: Logger) { addMultiblockEntity(entity) if (entity is PoweredMultiblockEntity) { - (getNetwork(NetworkType.POWER) as PowerNetwork).handleNewPoweredMultiblock(entity) + (getNetwork(NetworkType.POWER) as PowerNodeManager).handleNewPoweredMultiblock(entity) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 09b2494136..0af1c936b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -27,7 +27,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override fun save() {} - override fun getNetwork(type: NetworkType): TransportNetwork { + override fun getNetwork(type: NetworkType): NodeManager { return type.get(starship) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 13d5161c98..ee69baeef0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -134,5 +134,6 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< override fun toString(): String = "AREA SHIELD::: POWER:: ${getPower()}" + override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index a5abbc540e..2705dda6e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -33,6 +33,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.L import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.OPPOSITE import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.RIGHT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.SELF +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -272,6 +273,14 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock.isRequesting() || super.isRequesting() + } + companion object { const val WATER_INCREMENT = 5 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index 5eccb2e1b2..06341a3a37 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -21,6 +21,7 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GOLD @@ -152,6 +153,8 @@ object PipedGasCollectorMultiblock : Multiblock(), } } + override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) + override fun storeAdditionalData(store: PersistentMultiblockData) { val rawStorage = store.getAdditionalDataRaw() storeFluidData(rawStorage, rawStorage.adapterContext) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index f996e586e0..64b1972dc2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidSt import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.UnlimitedInternalStorage import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor @@ -39,5 +40,7 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), z: Int, world: World, structureDirection: BlockFace, - ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity + ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity { + override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 3228a69127..6a829c06b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -180,5 +181,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) } + + override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index c3a31cd6f1..7629d3c3ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -143,6 +144,8 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) } + override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) + override fun toString(): String { return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $structureDirection" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index d6b41a7761..e828e0c665 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -63,7 +63,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.thruster.ThrusterS import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.CustomTurretSubsystem -import net.horizonsend.ion.server.features.transport.ShipTransportManager +import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 0d7ee1ae7b..32dd66dc35 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -1,46 +1,40 @@ package net.horizonsend.ion.server.features.transport -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.network.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.Block class ChunkTransportManager( val chunk: IonChunk, ) { val scope = ChunkRegion.scope - val powerNetwork = ChunkNetworkHolder(this) { PowerNetwork(it) } -// val pipeGrid = PowerNetwork(this) // TODO -// val gasGrid = PowerNetwork(this) // TODO + val powerNodeManager = ChunkNetworkHolder(this) { PowerNodeManager(it) } +// val pipeGrid = PowerNodeManager(this) // TODO +// val gasGrid = PowerNodeManager(this) // TODO fun setup() { - powerNetwork.handleLoad() - // TODO - // TODO - } - - suspend fun tick() { - powerNetwork.network.tickIfReady() + powerNodeManager.handleLoad() // TODO // TODO } fun onUnload() { - powerNetwork.handleUnload() + powerNodeManager.handleUnload() // TODO // TODO } fun save() { - powerNetwork.save(chunk.inner.persistentDataContainer.adapterContext) + powerNodeManager.save(chunk.inner.persistentDataContainer.adapterContext) // TODO // TODO } fun processBlockRemoval(key: BlockKey) { - powerNetwork.network.processBlockRemoval(key) + powerNodeManager.network.processBlockRemoval(key) // TODO // TODO // pipeGrid.processBlockRemoval(key) @@ -48,18 +42,18 @@ class ChunkTransportManager( } fun processBlockRemovals(keys: Iterable) { - powerNetwork.network.processBlockRemovals(keys) + powerNodeManager.network.processBlockRemovals(keys) } - fun processBlockAddition(new: BlockSnapshot) { - powerNetwork.network.processBlockAddition(new) + fun processBlockAddition(new: Block) { + powerNodeManager.network.processBlockAddition(new) // TODO // TODO // pipeGrid.processBlockAddition(key, new) // gasGrid.processBlockAddition(key, new) } - fun processBlockAddition(changes: Iterable) { - powerNetwork.network.processBlockAdditions(changes) + fun processBlockAddition(changed: Iterable) { + powerNodeManager.network.processBlockAdditions(changed) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt index 4d59ffe292..99c47b2518 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt @@ -8,7 +8,6 @@ import com.sk89q.worldedit.function.pattern.Pattern import com.sk89q.worldedit.math.BlockVector3 import com.sk89q.worldedit.regions.Region import com.sk89q.worldedit.world.block.BlockStateHolder -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World @@ -57,13 +56,10 @@ class IonUpdateExtent(extent: Extent, val world: World, private val stage: EditS val newBlocks = region.clone().mapNotNull { position -> val newBlock = pattern.applyBlock(position) ?: return@mapNotNull null - val material = BukkitAdapter.adapt(newBlock.blockType) - val blockData = BukkitAdapter.adapt(newBlock.toBaseBlock()) - - BlockSnapshot(world, position.x, position.y, position.z, material, blockData) + BukkitAdapter.adapt(newBlock) } - TransportManager.handleBlockAdditions(world, newBlocks) +// TransportManager.handleBlockAdditions(world, newBlocks) } private fun handleUpdate(position: BlockVector3, newBlock: BlockStateHolder<*>?) { @@ -77,6 +73,6 @@ class IonUpdateExtent(extent: Extent, val world: World, private val stage: EditS val z = position.z TransportManager.handleBlockRemoval(world, toBlockKey(x, y, z)) - TransportManager.handleBlockAddition(world, BlockSnapshot(world, x, y, z, material, blockData)) +// TransportManager.handleBlockAddition(world, BlockSnapshot(world, x, y, z, material, blockData)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt index 2df0e7d251..fefba76cce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World +import org.bukkit.block.Block import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent @@ -26,10 +27,10 @@ object TransportManager : SLEventListener() { fun onBlockPlace(event: BlockPlaceEvent) { val world = event.block.world - handleBlockAddition(world, event.block.snapshot()) + handleBlockAddition(world, event.block) } - fun handleBlockAddition(world: World, new: BlockSnapshot) { + fun handleBlockAddition(world: World, new: Block) { val chunkX = new.x.shr(4) val chunkZ = new.z.shr(4) @@ -37,7 +38,7 @@ object TransportManager : SLEventListener() { chunk.transportNetwork.processBlockAddition(new) } - fun handleBlockAdditions(world: World, newBlocks: Iterable) { + fun handleBlockAdditions(world: World, newBlocks: Iterable) { for (new in newBlocks) { handleBlockAddition(world, new) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt new file mode 100644 index 0000000000..10af6333fb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.transport.grid + +import net.horizonsend.ion.server.features.transport.grid.util.Sink +import net.horizonsend.ion.server.features.transport.grid.util.Source + +class FluidGrid(manager: WorldGridManager) : Grid(GridType.Fluid, manager) { + override fun transferResources(from: Source, to: Sink, resistanceContribution: Int, totalResistance: Int) { +// TODO("Not yet implemented") + } + + override fun postMerge(other: Grid) { +// TODO("Not yet implemented") + } + + override fun postSplit(new: List) { +// TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt new file mode 100644 index 0000000000..350a715856 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt @@ -0,0 +1,106 @@ +package net.horizonsend.ion.server.features.transport.grid + +import com.google.common.graph.ElementOrder +import com.google.common.graph.GraphBuilder +import com.google.common.graph.MutableGraph +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.grid.util.Sink +import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import java.util.concurrent.ConcurrentHashMap + +@Suppress("UnstableApiUsage") +abstract class Grid(val type: GridType, val manager: WorldGridManager) { + private val sourceList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() + private val sinkList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() + + val nodes: ObjectOpenHashSet = ObjectOpenHashSet() + + val graph: MutableGraph = GraphBuilder + .undirected() + .nodeOrder(ElementOrder.unordered()) + .build() + + abstract fun transferResources(from: Source, to: Sink, resistanceContribution: Int, totalResistance: Int) + + fun tickTransport() { + for (source in sourceList) { + val sinkResistance = sinkList.associateWithNotNull { sink -> getLeastResistantPath(sink, source) } + + distributeResources(source, sinkResistance) + } + } + + private fun distributeResources(source: Source, sinks: Map) { + val total = sinks.values.sum() + + for ((sink, resistance) in sinks) { + transferResources(source, sink, resistance, total) + } + } + + /** + * Finds the path between the two sources with the least resistance, and returns the resistance value. Null if no path could be found. + **/ + fun getLeastResistantPath(to: Sink, from: Source): Int? { + return 1 //TODO A* + } + + fun addNode(node: TransportNode) { + node.grid = this + nodes.add(node) + graph.addNode(node) + + if (node is Source) { + sourceList.add(node) + } + } + + fun removeNode(node: TransportNode) { + nodes.remove(node) + graph.removeNode(node) + + if (nodes.isEmpty()) { + manager.removeGrid(this) + } + + if (node is Source) { + sourceList.remove(node) + } + } + + fun handleMerge(other: Grid) { + for (edge in other.graph.edges()) { + graph.putEdge(edge.nodeU(), edge.nodeV()) + } + + for (node in other.graph.nodes()) { + addNode(node) + graph.addNode(node) + node.grid = this + } + + postMerge(other) + } + + abstract fun postMerge(other: Grid) + + abstract fun postSplit(new: List) + + fun registerSource(source: Source) { + sourceList.add(source) + } + + fun removeSource(source: Source) { + sourceList.remove(source) + } + + fun registerSink(sink: Sink) { + sinkList.add(sink) + } + + fun removeSink(sink: Sink) { + sinkList.remove(sink) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt new file mode 100644 index 0000000000..1434ff1674 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt @@ -0,0 +1,17 @@ +package net.horizonsend.ion.server.features.transport.grid + +sealed class GridType { + abstract fun newInstance(manager: WorldGridManager): Grid + + data object Fluid : GridType() { + override fun newInstance(manager: WorldGridManager): Grid { + return FluidGrid(manager) + } + } + + data object Power : GridType() { + override fun newInstance(manager: WorldGridManager): Grid { + return PowerGrid(manager) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt new file mode 100644 index 0000000000..2b1e3c6d68 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.transport.grid + +import net.horizonsend.ion.server.features.transport.grid.util.Sink +import net.horizonsend.ion.server.features.transport.grid.util.Source + +class PowerGrid(manager: WorldGridManager) : Grid(GridType.Power, manager) { + override fun transferResources(from: Source, to: Sink, resistanceContribution: Int, totalResistance: Int) { +// TODO("Not yet implemented") + } + + override fun postMerge(other: Grid) { +// TODO("Not yet implemented") + } + + override fun postSplit(new: List) { +// TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt new file mode 100644 index 0000000000..c32a0f919a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt @@ -0,0 +1,104 @@ +package net.horizonsend.ion.server.features.transport.grid + +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.world.IonWorld +import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import java.lang.IndexOutOfBoundsException +import java.util.concurrent.ConcurrentHashMap + +class WorldGridManager(val world: IonWorld) { + val allGrids = ConcurrentHashMap.newKeySet() + private val byType: ConcurrentHashMap> = ConcurrentHashMap() + + private fun getGridsOfType(type: GridType): MutableSet { + return byType.getOrPut(type) { ConcurrentHashMap.newKeySet() } + } + + fun tickSafely() { + try { + tickTransport() + } catch (e: Throwable) { + return + } + } + + private fun tickTransport() { + allGrids.forEach { it.tickTransport() } + } + + fun registerGrid(grid: Grid) { + allGrids.add(grid) + getGridsOfType(grid.type).add(grid) + } + + fun removeGrid(grid: Grid) { + allGrids.remove(grid) + getGridsOfType(grid.type).remove(grid) + } + + @Suppress("UnstableApiUsage") + fun joinOrCreateGrid(node: TransportNode): Grid { + val relatedGrids = node.relationships.associateWithNotNull { + val sideTwoNode = it.sideTwo.node + if (!sideTwoNode.hasJoinedGrid()) return@associateWithNotNull null + sideTwoNode.grid + } + + return when (relatedGrids.entries.size) { + 0 -> createGrid(node) + + 1 -> { + val (neighbor, grid) = relatedGrids.entries.first() + grid.addNode(node) + grid.graph.putEdge(neighbor.sideTwo.node, node) + + grid + } + + in 2..Int.MAX_VALUE -> { + val new = mergeGrids(relatedGrids.values.toSet()) + for (neighbor in relatedGrids.keys) { + new.graph.putEdge(neighbor.sideTwo.node, node) + } + + new + } + + else -> throw IllegalArgumentException("Negative number of grids?") + } + } + + /** + * Combines the provided grid, and returns the resulting combination + **/ + fun mergeGrids(others: Set): T { + when (others.size) { + 0 -> throw IndexOutOfBoundsException("Attempted to merge 0 grids!") + 1 -> return others.first() + } + + val largest = others.maxBy { it.nodes.size } + + for (grid in others.minus(largest)) { + largest.handleMerge(grid) + + removeGrid(grid) + } + + return largest + } + + fun splitGrid(grid: T): List { + throw NotImplementedError() + } + + fun createGrid(origin: TransportNode): Grid { + val newGrid = origin.gridType.newInstance(this) + newGrid.addNode(origin) + getGridsOfType(origin.gridType).add(newGrid) + + registerGrid(newGrid) + + return newGrid + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt new file mode 100644 index 0000000000..3e72e383a6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt @@ -0,0 +1,45 @@ +package net.horizonsend.ion.server.features.transport.grid.util + +import com.google.common.graph.Graph +import java.util.LinkedList + +@Suppress("UnstableApiUsage") +fun separateGraphs(graph: Graph): List> { + val seen: MutableSet = HashSet() + val stack = LinkedList() + val separated: MutableList> = LinkedList() + + while (true) { + var first: T? = null + + // Find next node in graph we haven't seen. + for (node in graph.nodes()) { + if (!seen.contains(node)) { + first = node + break + } + } + + // We have discovered all nodes, exit. + if (first == null) break + + // Start recursively building out all nodes in this sub-graph + val subGraph: MutableSet = HashSet() + + stack.push(first) + + while (!stack.isEmpty()) { + val entry = stack.pop() + + if (seen.contains(entry)) continue + + stack.addAll(graph.adjacentNodes(entry)) + seen.add(entry) + subGraph.add(entry) + } + + separated.add(subGraph) + } + + return separated +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt new file mode 100644 index 0000000000..71859aef19 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid.util + +interface Sink { + fun isRequesting(): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt new file mode 100644 index 0000000000..eb12cb49b7 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid.util + +interface Source { + fun isProviding(): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index fbb27c959f..0c25ecfe6a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.data.BlockData -abstract class NodeFactory(val network: T) { +abstract class NodeFactory(val network: T) { /** * Create and handle placement of a node at the position, if one should be created **/ - abstract suspend fun create(key: BlockKey, snapshot: BlockSnapshot) + abstract suspend fun create(key: BlockKey, data: BlockData) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index f23636500b..44ba0791f9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.power.PowerDirectionalNode @@ -29,7 +29,7 @@ enum class NodeType(val clazz: Class) { //ITEM ; - fun newInstance(network: TransportNetwork): TransportNode { + fun newInstance(network: NodeManager): TransportNode { return clazz.getDeclaredConstructor(network::class.java).newInstance(network) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index 1ab30acfd2..a148a4ef0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -60,20 +60,20 @@ fun getNode(world: World, key: BlockKey, networkType: NetworkType): TransportNod enum class NetworkType { POWER { - override fun get(chunk: IonChunk): TransportNetwork { - return chunk.transportNetwork.powerNetwork.network + override fun get(chunk: IonChunk): NodeManager { + return chunk.transportNetwork.powerNodeManager.network } - override fun get(ship: ActiveStarship): TransportNetwork { + override fun get(ship: ActiveStarship): NodeManager { TODO("Not yet implemented") } }, FLUID { - override fun get(chunk: IonChunk): TransportNetwork { - return chunk.transportNetwork.powerNetwork.network + override fun get(chunk: IonChunk): NodeManager { + return chunk.transportNetwork.powerNodeManager.network } - override fun get(ship: ActiveStarship): TransportNetwork { + override fun get(ship: ActiveStarship): NodeManager { TODO("Not yet implemented") } }, @@ -81,6 +81,6 @@ enum class NetworkType { ; - abstract fun get(chunk: IonChunk): TransportNetwork - abstract fun get(ship: ActiveStarship): TransportNetwork + abstract fun get(chunk: IonChunk): NodeManager + abstract fun get(ship: ActiveStarship): NodeManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index eaef8a43ff..d2223aa087 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,7 +1,11 @@ package net.horizonsend.ion.server.features.transport.node +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.grid.Grid +import net.horizonsend.ion.server.features.transport.grid.GridType +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -14,15 +18,15 @@ import java.util.concurrent.ThreadLocalRandom /** * Represents a single node, or step, in transport transportNetwork **/ -interface TransportNode : PDCSerializable { - var isDead: Boolean - val network: TransportNetwork +abstract class TransportNode(val gridType: GridType) : PDCSerializable { + var isDead: Boolean = false + abstract val manager: NodeManager override val persistentDataType: Companion get() = Companion - /** - * Stored relationships between nodes - **/ - val relationships: MutableSet + lateinit var grid: Grid + + /** Stored relationships between nodes **/ + val relationships: MutableSet = ObjectOpenHashSet() /** * Break all relations between this node and others @@ -57,7 +61,7 @@ interface TransportNode : PDCSerializable> = relationships.filter { @@ -68,39 +72,49 @@ interface TransportNode : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java @@ -127,7 +141,7 @@ interface TransportNode : PDCSerializable(network) { - override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { +class FluidNodeFactory(network: FluidNodeManager) : NodeFactory(network) { + override suspend fun create(key: BlockKey, data: BlockData) { if (network.nodes.contains(key)) return when { // Straight wires - snapshot.type == Material.LIGHTNING_ROD -> addLightningRod(snapshot.data as Directional, key) + data.material == Material.LIGHTNING_ROD -> addLightningRod(data as Directional, key) // Omnidirectional wires - snapshot.type.isCopperBlock -> addJunction(key) + data.material.isCopperBlock -> addJunction(key) // Extractor - snapshot.type == Material.CRAFTING_TABLE -> println("TODO") + data.material == Material.CRAFTING_TABLE -> println("TODO") // Input - snapshot.type == Material.FLETCHING_TABLE -> println("TODO") + data.material == Material.FLETCHING_TABLE -> println("TODO") // Flow meter - snapshot.type == Material.OBSERVER -> println("TODO") + data.material == Material.OBSERVER -> println("TODO") // Merge - snapshot.type == Material.REDSTONE_BLOCK -> println("TODO") - snapshot.type == Material.IRON_BLOCK -> println("TODO") + data.material == Material.REDSTONE_BLOCK -> println("TODO") + data.material == Material.IRON_BLOCK -> println("TODO") // Inverted Merge - snapshot.type == Material.LAPIS_BLOCK -> println("TODO") + data.material == Material.LAPIS_BLOCK -> println("TODO") // Splitter - CustomBlocks.getByBlockData(snapshot.data) == CustomBlocks.ALUMINUM_BLOCK -> println("TODO") + CustomBlocks.getByBlockData(data) == CustomBlocks.ALUMINUM_BLOCK -> println("TODO") // Valve - snapshot.type.isChiseledCopper -> println("TODO") + data.material.isChiseledCopper -> println("TODO") // Filter - snapshot.type.isCopperBulb -> println("TODO") + data.material.isCopperBulb -> println("TODO") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt new file mode 100644 index 0000000000..37458501be --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +class GasDirectionalNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt new file mode 100644 index 0000000000..64b7ff890e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +class GasFilterNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt new file mode 100644 index 0000000000..61cae7a031 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +class GasFlowMeter { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt new file mode 100644 index 0000000000..87bfc5611e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +class GasInvertedDirectionalNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt new file mode 100644 index 0000000000..4952ca30a3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt @@ -0,0 +1,24 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +import net.horizonsend.ion.server.features.transport.grid.GridType +import net.horizonsend.ion.server.features.transport.node.general.JunctionNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +class GasJunctionNode(network: FluidNodeManager) : JunctionNode(network, GridType.Fluid) { + constructor(network: FluidNodeManager, origin: BlockKey) : this(network) { + positions.add(origin) + } + + override suspend fun addBack(position: BlockKey) { + manager.nodeFactory.addJunction(position, handleRelationships = false) + } + + override fun toString(): String { + return """ + [Gas Junction Node] + ${positions.size} positions + Relationships: ${relationships.joinToString { it.sideTwo.toString() }} + """.trimIndent() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt new file mode 100644 index 0000000000..3166c46cea --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +class GasValveNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt new file mode 100644 index 0000000000..64f5d14fec --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt @@ -0,0 +1,24 @@ +package net.horizonsend.ion.server.features.transport.node.fluid + +import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync +import net.horizonsend.ion.server.features.transport.grid.GridType +import net.horizonsend.ion.server.features.transport.node.general.LinearNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Axis +import org.bukkit.block.data.Directional + +class LightningRodNode(network: FluidNodeManager) : LinearNode(network, GridType.Fluid) { + constructor(network: FluidNodeManager, origin: Long, axis: Axis) : this(network) { + positions.add(origin) + this.axis = axis + } + + override suspend fun addBack(position: BlockKey) { + manager.nodeFactory.addLightningRod( + getBlockSnapshotAsync(manager.world, position)!!.data as Directional, + position, + handleRelationships = false + ) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt deleted file mode 100644 index b3b2f28213..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/FluidExtractorNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class FluidExtractorNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt deleted file mode 100644 index a599aa1c96..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasDirectionalNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class GasDirectionalNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt deleted file mode 100644 index 897a5a8f2e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFilterNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class GasFilterNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt deleted file mode 100644 index f98cc21bc9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasFlowMeter.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class GasFlowMeter { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt deleted file mode 100644 index 943a1c090e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInputNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class GasInputNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt deleted file mode 100644 index 73a23dce11..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasInvertedDirectionalNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class GasInvertedDirectionalNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt deleted file mode 100644 index f70c6b7f76..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasJunctionNode.kt +++ /dev/null @@ -1,23 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -import net.horizonsend.ion.server.features.transport.network.FluidNetwork -import net.horizonsend.ion.server.features.transport.node.general.JunctionNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey - -class GasJunctionNode(network: FluidNetwork) : JunctionNode(network) { - constructor(network: FluidNetwork, origin: BlockKey) : this(network) { - positions.add(origin) - } - - override suspend fun addBack(position: BlockKey) { - network.nodeFactory.addJunction(position, handleRelationships = false) - } - - override fun toString(): String { - return """ - [Gas Junction Node] - ${positions.size} positions - Relationships: ${relationships.joinToString { it.sideTwo.toString() }} - """.trimIndent() - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt deleted file mode 100644 index 8cd972c66f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/GasValveNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -class GasValveNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt deleted file mode 100644 index 73cffb2ab2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/gas/LightningRodNode.kt +++ /dev/null @@ -1,23 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.gas - -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.FluidNetwork -import net.horizonsend.ion.server.features.transport.node.general.LinearNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Axis -import org.bukkit.block.data.Directional - -class LightningRodNode(network: FluidNetwork) : LinearNode(network) { - constructor(network: FluidNetwork, origin: Long, axis: Axis) : this(network) { - positions.add(origin) - this.axis = axis - } - - override suspend fun addBack(position: BlockKey) { - network.nodeFactory.addLightningRod( - getBlockSnapshotAsync(network.world, position)!!.data as Directional, - position, - handleRelationships = false - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index ba4e8fa26b..65e3f99dce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -1,23 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.general -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -abstract class JunctionNode, B: JunctionNode>(override val network: T) : MultiNode { - override var isDead: Boolean = false - override val positions: MutableSet = LongOpenHashSet() - override val relationships: MutableSet = ObjectOpenHashSet() - +abstract class JunctionNode, B: JunctionNode>(override val manager: T, type: GridType) : MultiNode(type) { override fun isTransferableTo(node: TransportNode): Boolean { return node !is PowerExtractorNode && node !is SolarPanelNode } @@ -30,19 +23,4 @@ abstract class JunctionNode, B: Ju override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } - - abstract suspend fun addBack(position: BlockKey) - - override suspend fun rebuildNode(position: BlockKey) { - // Create new nodes, automatically merging together - positions.forEach { - // Do not handle relations - addBack(it) - } - - // Handle relations once fully rebuilt - positions.forEach { - network.nodes[it]?.buildRelations(it) - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index 65c930c647..16e09feda3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -1,11 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.general import com.manya.pdc.base.EnumDataType -import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.TransportNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode @@ -18,34 +16,17 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -abstract class LinearNode, B: LinearNode>(override val network: T) : MultiNode { - override var isDead: Boolean = false - override val positions: MutableSet = LongOpenHashSet() - override val relationships: MutableSet = ObjectOpenHashSet() +abstract class LinearNode, B: LinearNode>(override val manager: T, type: GridType) : MultiNode(type) { var axis by Delegates.notNull() override fun isTransferableTo(node: TransportNode): Boolean { return node !is PowerExtractorNode && node !is SolarPanelNode } - abstract suspend fun addBack(position: BlockKey) - - override suspend fun rebuildNode(position: BlockKey) { - // Create new nodes, automatically merging together - positions.forEach { - addBack(it) - } - - // Handle relations once fully rebuilt - positions.forEach { - network.nodes[it]?.buildRelations(it) - } - } - override suspend fun buildRelations(position: BlockKey) { for (offset in axis.faces.toList()) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.getNode(offsetKey) ?: continue + val neighborNode = manager.getNode(offsetKey) ?: continue if (this == neighborNode) continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/FluidNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt similarity index 61% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/FluidNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index 890491c16c..7c24577dc0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/FluidNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -1,15 +1,15 @@ -package net.horizonsend.ion.server.features.transport.network +package net.horizonsend.ion.server.features.transport.node.manager -import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.gas.FluidExtractorNode -import net.horizonsend.ion.server.features.transport.node.gas.FluidNodeFactory +import net.horizonsend.ion.server.features.transport.node.fluid.FluidExtractorNode +import net.horizonsend.ion.server.features.transport.node.fluid.FluidNodeFactory +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.GAS_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap -class FluidNetwork(holder: NetworkHolder) : TransportNetwork(holder) { +class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val namespacedKey: NamespacedKey = GAS_TRANSPORT override val type: NetworkType = NetworkType.FLUID override val nodeFactory = FluidNodeFactory(this) @@ -18,10 +18,6 @@ class FluidNetwork(holder: NetworkHolder) : TransportNetwork(holde override val dataVersion: Int = 0 - override suspend fun tick() { - - } - override fun clearData() { nodes.clear() extractors.clear() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt similarity index 66% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 0773b57084..9f8f3d7a22 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/TransportNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -1,21 +1,19 @@ -package net.horizonsend.ion.server.features.transport.network +package net.horizonsend.ion.server.features.transport.node.manager import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.NamespacedKey +import org.bukkit.block.Block import org.bukkit.persistence.PersistentDataContainer import java.util.concurrent.ConcurrentHashMap -abstract class TransportNetwork(val holder: NetworkHolder<*>) { - var ready: Boolean = false - +abstract class NodeManager(val holder: NetworkHolder<*>) { val nodes: ConcurrentHashMap = ConcurrentHashMap() val world get() = holder.getWorld() @@ -25,43 +23,43 @@ abstract class TransportNetwork(val holder: NetworkHolder<*>) { abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int - open fun processBlockRemoval(key: BlockKey) { holder.scope.launch { withTransportDisabled { - val previousNode = nodes[key] ?: return@withTransportDisabled + open fun processBlockRemoval(key: BlockKey) { holder.scope.launch { + val previousNode = nodes[key] ?: return@launch previousNode.handleRemoval(key) - }}} + }} - open fun processBlockRemovals(keys: Iterable) { holder.scope.launch { withTransportDisabled { + open fun processBlockRemovals(keys: Iterable) { holder.scope.launch { for (key in keys) { - val previousNode = nodes[key] ?: return@withTransportDisabled + val previousNode = nodes[key] ?: return@launch previousNode.handleRemoval(key) } - }}} + }} - open fun processBlockAddition(new: BlockSnapshot) { holder.scope.launch { + open fun processBlockAddition(new: Block) { holder.scope.launch { if (new.type.isAir) { processBlockRemoval(toBlockKey(new.x, new.y, new.z)) return@launch } - withTransportDisabled { createNodeFromBlock(new) } + createNodeFromBlock(new) }} - open fun processBlockAdditions(changes: Iterable) { holder.scope.launch { withTransportDisabled { - for (new in changes) { + open fun processBlockAdditions(changed: Iterable) { holder.scope.launch { + for (new in changed) { createNodeFromBlock(new) } - }}} + }} /** * Handle the creation / loading of the node into memory **/ - suspend fun createNodeFromBlock(block: BlockSnapshot) { + suspend fun createNodeFromBlock(block: Block) { val key = toBlockKey(block.x, block.y, block.z) - withTransportDisabled { nodeFactory.create(key, block) } + nodeFactory.create(key, block.blockData) } /** @@ -69,12 +67,6 @@ abstract class TransportNetwork(val holder: NetworkHolder<*>) { **/ open fun saveAdditional(pdc: PersistentDataContainer) {} - suspend fun tickIfReady() { - if (ready) tick() - } - - abstract suspend fun tick() - abstract fun clearData() /** @@ -97,7 +89,11 @@ abstract class TransportNetwork(val holder: NetworkHolder<*>) { /** * Handles any cleanup tasks at the end of loading **/ - open fun finalizeNodes() {} + open fun finalizeNodes() { + for ((_, node) in nodes) { + node.joinGrid() + } + } fun breakAllRelations() { runBlocking { nodes.values.forEach { it.clearRelations() } } @@ -114,14 +110,4 @@ abstract class TransportNetwork(val holder: NetworkHolder<*>) { fun getNode(key: BlockKey, allowNeighborChunks: Boolean = true): TransportNode? { return if (allowNeighborChunks) holder.getGlobalNode(key) else holder.getInternalNode(key) } - - protected suspend inline fun withTransportDisabled(crossinline block: suspend () -> Unit) { - ready = false - - try { - block.invoke() - } finally { - ready = true - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt similarity index 79% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index f9df2bab00..78b16c16b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/PowerNetwork.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.transport.network +package net.horizonsend.ion.server.features.transport.node.manager import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.transport.network.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory @@ -16,7 +16,7 @@ import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -class PowerNetwork(holder: NetworkHolder) : TransportNetwork(holder) { +class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER override val namespacedKey: NamespacedKey = POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) @@ -28,23 +28,6 @@ class PowerNetwork(holder: NetworkHolder) : TransportNetwork(holde override val dataVersion: Int = 0 //TODO 1 - private suspend fun tickSolarPanels() { - for (solarPanel in solarPanels) { - - } - } - - private suspend fun tickExtractors() { - extractors.forEach { (key, extractor) -> - - } - } - - override suspend fun tick() { - tickSolarPanels() - tickExtractors() - } - override fun clearData() { nodes.clear() solarPanels.clear() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt similarity index 81% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index a3fd3c6cf2..794bc9cad7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 7dcba33a4b..56c8406268 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -1,14 +1,13 @@ -package net.horizonsend.ion.server.features.transport.network.holders +package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -21,7 +20,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { +class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { override var network: T by Delegates.notNull(); private set constructor(manager: ChunkTransportManager, network: (ChunkNetworkHolder) -> T) : this(manager) { @@ -84,8 +83,6 @@ class ChunkNetworkHolder private constructor (val manager: network.buildRelations() network.finalizeNodes() - - network.ready = true } } @@ -177,9 +174,7 @@ class ChunkNetworkHolder private constructor (val manager: for (z: Int in 0..15) { val realZ = originZ + z - val snapshot = getBlockSnapshotAsync(manager.chunk.world, realX, realY, realZ) ?: continue - - network.createNodeFromBlock(snapshot) + network.createNodeFromBlock(manager.chunk.world.getBlockAt(realX, realY, realZ)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt similarity index 80% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index b1c74c41e1..8d1f707a7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -1,12 +1,12 @@ -package net.horizonsend.ion.server.features.transport.network.holders +package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope -import net.horizonsend.ion.server.features.transport.network.TransportNetwork import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World -interface NetworkHolder { +interface NetworkHolder { val network: T val scope: CoroutineScope diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt similarity index 84% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index bae53a3a1c..1b3d614454 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/network/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -1,15 +1,15 @@ -package net.horizonsend.ion.server.features.transport.network.holders +package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.network.TransportNetwork +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World import kotlin.properties.Delegates -class ShipNetworkHolder(val starship: ActiveStarship) : NetworkHolder { +class ShipNetworkHolder(val starship: ActiveStarship) : NetworkHolder { override var network: T by Delegates.notNull(); private set constructor(manager: ActiveStarship, network: (ShipNetworkHolder) -> T) : this(manager) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index f4fd647b11..ac5e94d92a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -1,21 +1,22 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.general.LinearNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.block.data.Directional -class EndRodNode(network: PowerNetwork) : LinearNode(network) { - constructor(network: PowerNetwork, origin: Long, axis: Axis) : this(network) { +class EndRodNode(network: PowerNodeManager) : LinearNode(network, GridType.Power) { + constructor(network: PowerNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis } override suspend fun addBack(position: BlockKey) { - network.nodeFactory.addEndRod( - getBlockSnapshotAsync(network.world, position)!!.data as Directional, + manager.nodeFactory.addEndRod( + getBlockSnapshotAsync(manager.world, position)!!.data as Directional, position, handleRelationships = false ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index a500d83591..5a5dff047c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -1,22 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates -class InvertedDirectionalNode(override val network: PowerNetwork) : SingleNode { - override var isDead: Boolean = false - override var position: BlockKey by Delegates.notNull() - override val relationships: MutableSet = ObjectOpenHashSet() - - constructor(network: PowerNetwork, position: BlockKey) : this(network) { +class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { + constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index e73dced21c..dc0cc756c5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -1,10 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -13,13 +12,10 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerDirectionalNode(override val network: PowerNetwork) : SingleNode { - override var isDead: Boolean = false - override var position: BlockKey by Delegates.notNull() +class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { private var variant: Material by Delegates.notNull() - override val relationships: MutableSet = ObjectOpenHashSet() - constructor(network: PowerNetwork, position: BlockKey, variant: Material) : this(network) { + constructor(network: PowerNodeManager, position: BlockKey, variant: Material) : this(network) { this.position = position this.variant = variant } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index ed1d02423c..d333c28c05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -1,22 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates -class PowerEqualSplitterNode(override val network: PowerNetwork) : SingleNode { - override var isDead: Boolean = false - override var position: BlockKey by Delegates.notNull() - override val relationships: MutableSet = ObjectOpenHashSet() - - constructor(network: PowerNetwork, position: BlockKey) : this(network) { +class PowerEqualSplitterNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { + constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 686d118e02..b8494fe96b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType +import net.horizonsend.ion.server.features.transport.grid.util.Source import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -13,18 +13,13 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt -import kotlin.properties.Delegates -class PowerExtractorNode(override val network: PowerNetwork) : SingleNode { - constructor(network: PowerNetwork, position: BlockKey) : this(network) { +class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power), Source { + constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this } - override var isDead: Boolean = false - override var position by Delegates.notNull() - override val relationships: MutableSet = ObjectOpenHashSet() - val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } // Region transfer @@ -41,6 +36,7 @@ class PowerExtractorNode(override val network: PowerNetwork) : SingleNode { } private var lastTicked: Long = System.currentTimeMillis() + fun markTicked() { lastTicked = System.currentTimeMillis() } @@ -63,18 +59,18 @@ class PowerExtractorNode(override val network: PowerNetwork) : SingleNode { override fun loadIntoNetwork() { super.loadIntoNetwork() - network.extractors[position] = this + manager.extractors[position] = this } override suspend fun handleRemoval(position: BlockKey) { - network.extractors.remove(position) + manager.extractors.remove(position) super.handleRemoval(position) } override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.getNode(offsetKey) ?: continue + val neighborNode = manager.getNode(offsetKey) ?: continue if (this == neighborNode) return @@ -87,6 +83,10 @@ class PowerExtractorNode(override val network: PowerNetwork) : SingleNode { } } + override fun isProviding(): Boolean { + return extractableNodes.mapNotNull { it.boundMultiblockEntity }.any { it.getPower() > 0 } + } + override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 4e6a0ca8c9..af777359d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -1,16 +1,15 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -24,18 +23,14 @@ import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.NORTH import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates -class PowerFlowMeter(override val network: PowerNetwork) : SingleNode { - constructor(network: PowerNetwork, position: BlockKey, direction: BlockFace) : this(network) { +class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { + constructor(network: PowerNodeManager, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction } - override var position by Delegates.notNull() - override var isDead: Boolean = false - override val relationships: MutableSet = ObjectOpenHashSet() - var direction: BlockFace by Delegates.notNull() + lateinit var direction: BlockFace /* * Should transfer power like any normal node. @@ -97,7 +92,7 @@ class PowerFlowMeter(override val network: PowerNetwork) : SingleNode { private fun setupDisplayEntity() { displayHandler = DisplayHandlers.newBlockOverlay( - network.world, + manager.world, toVec3i(position), direction, PowerFlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index f2bbdf9e24..b8338e504d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,63 +1,22 @@ package net.horizonsend.ion.server.features.transport.node.power -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.network.holders.ChunkNetworkHolder -import net.horizonsend.ion.server.features.transport.network.holders.ShipNetworkHolder -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates -class PowerInputNode(override val network: PowerNetwork) : SingleNode { - constructor(network: PowerNetwork, position: BlockKey) : this(network) { +class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { + constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } - override var isDead: Boolean = false - override var position by Delegates.notNull() - override val relationships: MutableSet = ObjectOpenHashSet() - override fun isTransferableTo(node: TransportNode): Boolean { - return node is PowerExtractorNode - } - - override suspend fun buildRelations(position: BlockKey) { - super.buildRelations(position) - } - - fun getPoweredMultiblocks(): Iterable { - val x = getX(position) - val y = getY(position) - val z = getZ(position) - - return offsets.mapNotNull { offset -> - val newX = x + offset.x - val newY = y + offset.y - val newZ = z + offset.z - - val newKey = toBlockKey(newX, newY, newZ) - - return@mapNotNull when (val holder = network.holder) { - is ChunkNetworkHolder<*> -> { - holder.manager.chunk.multiblockManager[newKey] as? PoweredMultiblockEntity - } - is ShipNetworkHolder<*> -> { - null //TODO - } - else -> null - } - } + return false } override fun storeData(persistentDataContainer: PersistentDataContainer) { @@ -68,20 +27,7 @@ class PowerInputNode(override val network: PowerNetwork) : SingleNode { position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } - companion object { - private val offsets = setOf( - // most multiblocks have the sign a block up and out of the computer - Vec3i(1, 1, 0), Vec3i(-1, 1, 0), Vec3i(0, 1, -1), Vec3i(0, 1, 1), - // power cells have it on the block - Vec3i(1, 0, 0), Vec3i(-1, 0, 0), Vec3i(0, 0, -1), Vec3i(0, 0, 1), - // drills have it on a corner - Vec3i(-1, 0, -1), Vec3i(1, 0, -1), Vec3i(1, 0, 1), Vec3i(-1, 0, 1), - // upside down mining lasers have signs below - Vec3i(1, -1, 0), Vec3i(-1, -1, 0), Vec3i(0, -1, -1), Vec3i(0, -1, 1), - // up and down - Vec3i(0, 1, 0), Vec3i(0, -1, 0) - ) - } + var boundMultiblockEntity: PoweredMultiblockEntity? = null - override fun toString(): String = "POWER INPUT NODE: ${getPoweredMultiblocks().toList().size} powered multiblocks, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" + override fun toString(): String = "POWER INPUT NODE. Bound to $boundMultiblockEntity Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index d9ea787f89..0930dc00df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -1,11 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.transport.network.PowerNetwork import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.handleMerges +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode.Companion.matchesSolarPanelStructure import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis @@ -16,21 +15,22 @@ import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.BlockFace.UP +import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional -class PowerNodeFactory(network: PowerNetwork) : NodeFactory(network) { - override suspend fun create(key: BlockKey, snapshot: BlockSnapshot) { +class PowerNodeFactory(network: PowerNodeManager) : NodeFactory(network) { + override suspend fun create(key: BlockKey, data: BlockData) { if (network.nodes.contains(key)) return when { // Straight wires - snapshot.type == Material.END_ROD -> addEndRod(snapshot.data as Directional, key) + data.material == Material.END_ROD -> addEndRod(data as Directional, key) // Omnidirectional wires - snapshot.type == Material.SPONGE -> addSponge(key) + data.material == Material.SPONGE -> addSponge(key) // Extract power from storage - snapshot.type == Material.CRAFTING_TABLE -> { + data.material == Material.CRAFTING_TABLE -> { if (matchesSolarPanelStructure(network.world, key)) { addSolarPanel(key) } else { @@ -39,7 +39,7 @@ class PowerNodeFactory(network: PowerNetwork) : NodeFactory(networ } // Check for extractor beneath - snapshot.type == Material.DIAMOND_BLOCK -> { + data.material == Material.DIAMOND_BLOCK -> { val extractorKey = getRelative(key, DOWN, 1) if (matchesSolarPanelStructure(network.world, extractorKey)) { @@ -48,7 +48,7 @@ class PowerNodeFactory(network: PowerNetwork) : NodeFactory(networ } } - snapshot.type == Material.DAYLIGHT_DETECTOR -> { + data.material == Material.DAYLIGHT_DETECTOR -> { val extractorKey = getRelative(key, DOWN, 2) if (matchesSolarPanelStructure(network.world, extractorKey)) { @@ -58,17 +58,17 @@ class PowerNodeFactory(network: PowerNetwork) : NodeFactory(networ } // Add power to storage - snapshot.type == Material.NOTE_BLOCK -> addInput(key) + data.material == Material.NOTE_BLOCK -> addInput(key) // Power flow meter - snapshot.type == Material.OBSERVER -> addFlowMeter(snapshot.data as Directional, key) + data.material == Material.OBSERVER -> addFlowMeter(data as Directional, key) // Merge node behavior - snapshot.type == Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) - snapshot.type == Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) + data.material == Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) + data.material == Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) // Split power evenly - CustomBlocks.getByBlockData(snapshot.data) == CustomBlocks.ALUMINUM_BLOCK -> addEqualSplitterNode(key) + CustomBlocks.getByBlockData(data) == CustomBlocks.ALUMINUM_BLOCK -> addEqualSplitterNode(key) // Redstone controlled gate // block.type.isRedstoneLamp -> GateNode(this, x, y, z) @@ -172,7 +172,7 @@ class PowerNodeFactory(network: PowerNetwork) : NodeFactory(networ val node = when (neighboringNodes.size) { 0 -> SolarPanelNode(network).apply { - network.solarPanels += this + manager.solarPanels += this }.addPosition(position, diamondPosition, detectorPosition) 1 -> neighboringNodes.firstOrNull()?.addPosition(position, diamondPosition, detectorPosition) ?: throw ConcurrentModificationException("Node removed during processing") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index d0223edb5a..354369c690 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.network.PowerNetwork -import net.horizonsend.ion.server.features.transport.node.NodeRelationship +import net.horizonsend.ion.server.features.transport.grid.GridType +import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS @@ -13,6 +14,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.firsts import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.GameRule @@ -30,12 +32,8 @@ import java.util.function.Consumer * Represents a solar panel, or multiple **/ class SolarPanelNode( - override val network: PowerNetwork -) : MultiNode { - override var isDead: Boolean = false - override val positions: MutableSet = ConcurrentHashMap.newKeySet() - override val relationships: MutableSet = ConcurrentHashMap.newKeySet() - + override val manager: PowerNodeManager +) : MultiNode(GridType.Power), Source { /** The positions of extractors in this solar panel */ private val extractorPositions = ConcurrentHashMap.newKeySet() @@ -101,8 +99,8 @@ class SolarPanelNode( **/ fun getPower(): Int { val daylightMultiplier: Double = if ( - network.world.environment == World.Environment.NORMAL && - network.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true + manager.world.environment == World.Environment.NORMAL && + manager.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true ) { getPowerRatio() } else 0.5 @@ -113,13 +111,17 @@ class SolarPanelNode( return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() } + override fun isProviding(): Boolean { + return getPower() > 0 + } + /** * Calculates the light level at the detectors **/ private fun getPowerRatio(): Double { val total = detectorPositions.size * 15 val sum = detectorPositions.sumOf { - val data = getBlockDataSafe(network.world, getX(it), getY(it), getZ(it)) ?: return@sumOf 0 + val data = getBlockDataSafe(manager.world, getX(it), getY(it), getZ(it)) ?: return@sumOf 0 if (data !is AnaloguePowerable) return@sumOf 0 data.power @@ -168,11 +170,13 @@ class SolarPanelNode( override suspend fun handleRemoval(position: BlockKey) { isDead = true + grid.removeNode(this) + removePosition(position) // Remove all positions positions.forEach { - network.nodes.remove(it) + manager.nodes.remove(it) } // Rebuild relations after cleared @@ -186,7 +190,7 @@ class SolarPanelNode( extractorPositions += extractorKey // Make sure there isn't still an extractor - network.extractors.remove(extractorKey) + manager.extractors.remove(extractorKey) addPosition(extractorKey) buildRelations(extractorKey) @@ -196,7 +200,7 @@ class SolarPanelNode( detectorPositions += detectorKey for (position: BlockKey in positions) { - network.nodes[position] = this + manager.nodes[position] = this buildRelations(position) } @@ -212,39 +216,28 @@ class SolarPanelNode( positions.remove(extractorPos) extractorPositions.remove(extractorPos) - network.nodes.remove(extractorPos) + manager.nodes.remove(extractorPos) for (otherPos: BlockKey in otherPositions) { positions.remove(otherPos) - network.nodes.remove(otherPos) + manager.nodes.remove(otherPos) } } - override suspend fun rebuildNode(position: BlockKey) { - network.solarPanels.remove(this) - detectorPositions.clear() - - // Create new nodes, automatically merging together - extractorPositions.forEach { - network.nodeFactory.addSolarPanel(it, handleRelationships = false) - } - - // Handle relations once fully rebuilt - positions.forEach { - network.nodes[it]?.buildRelations(it) - } + override suspend fun addBack(position: BlockKey) { + manager.nodeFactory.addSolarPanel(position, handleRelationships = false) } - override suspend fun drainTo(new: SolarPanelNode) { - super.drainTo(new) + override suspend fun rebuildNode(position: BlockKey) { + manager.solarPanels.remove(this) + detectorPositions.clear() - new.extractorPositions.addAll(extractorPositions) - new.detectorPositions.addAll(detectorPositions) + super.rebuildNode(position) } override fun loadIntoNetwork() { super.loadIntoNetwork() - network.solarPanels += this + manager.solarPanels += this } override fun storeData(persistentDataContainer: PersistentDataContainer) { @@ -278,5 +271,5 @@ class SolarPanelNode( } } - override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().firsts().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance, powerRatio = ${getPowerRatio()}" + override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().firsts().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance, powerRatio = ${getPowerRatio()}, location = ${toVec3i(positions.random())}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index a275108859..8826d394be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -1,22 +1,24 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.network.PowerNetwork +import net.horizonsend.ion.server.features.transport.grid.GridType +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i /** * Represents a sponge [omnidirectional pipe] * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(network: PowerNetwork) : JunctionNode(network) { - constructor(network: PowerNetwork, origin: BlockKey) : this(network) { +class SpongeNode(network: PowerNodeManager) : JunctionNode(network, GridType.Power) { + constructor(network: PowerNodeManager, origin: BlockKey) : this(network) { positions.add(origin) } override suspend fun addBack(position: BlockKey) { - network.nodeFactory.addSponge(position, handleRelationships = false) + manager.nodeFactory.addSponge(position, handleRelationships = false) } - override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.first.javaClass.simpleName }} nodes)" + override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.first.javaClass.simpleName }} nodes) location = ${toVec3i(positions.random())}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 929a8d4401..71117b2d24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.type +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -8,9 +10,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative /** * A transport node that may cover many blocks to avoid making unnecessary steps **/ -interface MultiNode, Z: MultiNode> : TransportNode { +abstract class MultiNode, Z: MultiNode>(type: GridType) : TransportNode(type) { /** The positions occupied by the node **/ - val positions: MutableSet + val positions: MutableSet = LongOpenHashSet() /** * Rebuild the node during the removal process @@ -18,14 +20,31 @@ interface MultiNode, Z: MultiNode> : Transport * When a position in a multi node is removed, the removed position is removed * from the list of contained positions, and the node is rebuilt using this method. **/ - suspend fun rebuildNode(position: BlockKey) + open suspend fun rebuildNode(position: BlockKey) { + // Create new nodes, automatically merging together + positions.forEach { + addBack(it) + } + + // Handle relations once fully rebuilt + positions.forEach { + manager.nodes[it]?.buildRelations(it) + } + + // Join successor nodes to the grid + positions + .mapNotNullTo(mutableSetOf()) { manager.nodes[it] } + .forEach { it.joinGrid() } + } + + abstract suspend fun addBack(position: BlockKey) /** * Adds new a position to this node **/ suspend fun addPosition(position: BlockKey): Self { positions += position - network.nodes[position] = this + manager.nodes[position] = this onPlace(position) @@ -39,7 +58,7 @@ interface MultiNode, Z: MultiNode> : Transport suspend fun addPositions(newPositions: Iterable) { for (position in newPositions) { positions += position - network.nodes[position] = this + manager.nodes[position] = this onPlace(position) } @@ -52,6 +71,8 @@ interface MultiNode, Z: MultiNode> : Transport clearRelations() new.clearRelations() + grid.removeNode(this) + new.addPositions(positions) new.positions.forEach { new.buildRelations(it) } } @@ -59,7 +80,7 @@ interface MultiNode, Z: MultiNode> : Transport override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.getNode(offsetKey) ?: continue + val neighborNode = manager.getNode(offsetKey) ?: continue if (this == neighborNode) continue @@ -78,14 +99,16 @@ interface MultiNode, Z: MultiNode> : Transport override suspend fun handleRemoval(position: BlockKey) { isDead = true + grid.removeNode(this) + // Remove the position from the network - network.nodes.remove(position) + manager.nodes.remove(position) // Remove the position from this node positions.remove(position) // Remove all positions positions.forEach { - network.nodes.remove(it) + manager.nodes.remove(it) } // Rebuild relations after cleared @@ -95,11 +118,9 @@ interface MultiNode, Z: MultiNode> : Transport rebuildNode(position) } - override suspend fun onPlace(position: BlockKey) {} - override fun loadIntoNetwork() { for (key in positions) { - network.nodes[key] = this + manager.nodes[key] = this } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 67631959fa..fa1db29cbe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -1,24 +1,26 @@ package net.horizonsend.ion.server.features.transport.node.type +import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import kotlin.properties.Delegates /** * A node that only occupies a single block **/ -interface SingleNode : TransportNode { - val position: Long +abstract class SingleNode(type: GridType) : TransportNode(type) { + var position by Delegates.notNull() override fun loadIntoNetwork() { - network.nodes[position] = this + manager.nodes[position] = this } override suspend fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) - val neighborNode = network.getNode(offsetKey) ?: continue + val neighborNode = manager.getNode(offsetKey) ?: continue if (this == neighborNode) return @@ -29,11 +31,13 @@ interface SingleNode : TransportNode { override suspend fun onPlace(position: BlockKey) { buildRelations(position) + joinGrid() } override suspend fun handleRemoval(position: BlockKey) { isDead = true - network.nodes.remove(position) + manager.nodes.remove(position) clearRelations() + grid.removeNode(this) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 8eebf450bb..de5c496d44 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.manager.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship +import net.horizonsend.ion.server.features.transport.grid.WorldGridManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.configuration.DefaultWorldConfiguration @@ -51,6 +52,7 @@ class IonWorld private constructor( val chunkRegions: MutableSet = ObjectOpenHashSet() val multiblockManager = WorldMultiblockManager(this) + val gridManager = WorldGridManager(this) /** * Gets the IonChunk at the specified coordinates if it is loaded @@ -194,6 +196,8 @@ class IonWorld private constructor( mainThreadCheck() for (ionWorld in ionWorlds.values) { + ionWorld.gridManager.tickSafely() + for (starship in ionWorld.starships) { val result = runCatching(starship::tick).exceptionOrNull() ?: continue log.warn("Exception while ticking starship!", result) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index 6b7aae51e9..1034cf2134 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -20,7 +20,6 @@ class ChunkRegion(val world: IonWorld) { fun tickChunkTransport() { scope.launch { for ((_, chunk) in chunks) { - chunk.transportNetwork.tick() chunk.multiblockManager.tick() } } From d3bf7a038e8dc68c8e786342cb3a1f184b7f52fe Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 17:43:43 -0500 Subject: [PATCH 157/500] update multiblock manager --- .../ion/server/features/multiblock/entity/MultiblockEntity.kt | 2 +- .../features/multiblock/manager/ShipMultiblockManager.kt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 3dc83fabd1..28961647f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -28,7 +28,7 @@ import org.bukkit.block.Sign * @param structureDirection The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( - val manager: MultiblockManager, + var manager: MultiblockManager, open val multiblock: Multiblock, var x: Int, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 0af1c936b3..8fe667b685 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -44,6 +44,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe manager.getAllMultiblockEntities()[modernBlockKey]?.let { multiblockEntities[modernBlockKey] = it + it.manager = this manager.getAllMultiblockEntities().remove(modernBlockKey) } ?: return@iterateBlocks @@ -72,6 +73,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe } network.getAllMultiblockEntities()[key] = multiblockEntity + multiblockEntity.manager = network } for ((key, multiblockEntity) in syncTickingMultiblockEntities) { From 67f129c6b876d3fb1b0c8365290e043024847099 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 17:59:49 -0500 Subject: [PATCH 158/500] update displays properly --- .../server/features/client/display/modular/display/Display.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index a4f01e59be..c14a9dcdc3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -120,11 +120,12 @@ abstract class Display( fun display() { if (!::handler.isInitialized) return - setText(getText()) update() } fun update() { + setText(getText()) + val chunk = entity.level().world.getChunkAtIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return val playerChunk = chunk.minecraft.playerChunk ?: return From 0d787acf984ec0104e3a9b9053e8910236553108 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 17:59:55 -0500 Subject: [PATCH 159/500] fix --- .../server/features/multiblock/MultiblockAccess.kt | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index e732523104..426262b92c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -25,18 +25,14 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isSign -import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.block.data.type.WallSign import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.block.Action import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.block.BlockPhysicsEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.inventory.EquipmentSlot @@ -295,14 +291,4 @@ object MultiblockAccess : IonServerComponent() { event.player.information("Destroyed ${removed.name}") } - - @EventHandler - fun onBlockPhysics(event: BlockPhysicsEvent) { - if (!event.changedType.isWallSign) return - val data = event.changedBlockData as WallSign - val supportingBlock = event.block.getRelativeIfLoaded(data.facing.oppositeFace) ?: return - if (supportingBlock.type.isAir) return - - removeMultiblock(event.block.world, supportingBlock.x, supportingBlock.y, supportingBlock.z, data.facing.oppositeFace) - } } From 8ef1ca4a89092ddf216bf5cf3a70eb0080ebf5cf Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 20:41:49 -0500 Subject: [PATCH 160/500] different sources and sinks --- .../entity/type/fluids/FluidStoringEntity.kt | 4 +- .../type/power/PoweredMultiblockEntity.kt | 6 +-- .../type/power/storage/PowerBankMultiblock.kt | 7 ++- .../features/transport/grid/FluidGrid.kt | 12 ++--- .../server/features/transport/grid/Grid.kt | 45 +++++++++++-------- .../features/transport/grid/GridType.kt | 6 +-- .../features/transport/grid/PowerGrid.kt | 27 ++++++++--- .../transport/grid/WorldGridManager.kt | 21 ++++----- .../transport/grid/sink/FluidSource.kt | 3 ++ .../transport/grid/sink/PowerSource.kt | 5 +++ .../features/transport/grid/sink/Sink.kt | 5 +++ .../features/transport/grid/sink/Source.kt | 5 +++ .../features/transport/grid/util/Sink.kt | 5 --- .../features/transport/grid/util/Source.kt | 5 --- .../features/transport/node/TransportNode.kt | 6 +-- .../node/power/PowerExtractorNode.kt | 8 +++- .../transport/node/power/PowerInputNode.kt | 2 +- .../transport/node/power/SolarPanelNode.kt | 10 +++-- .../features/transport/node/type/MultiNode.kt | 3 ++ 19 files changed, 113 insertions(+), 72 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 5246b95212..e944568b9e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.grid.FluidGrid -import net.horizonsend.ion.server.features.transport.grid.util.Sink -import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.transport.grid.sink.Sink +import net.horizonsend.ion.server.features.transport.grid.sink.Source import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 154c7b1ba2..f75f82adc3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.transport.grid.PowerGrid -import net.horizonsend.ion.server.features.transport.grid.util.Sink +import net.horizonsend.ion.server.features.transport.grid.sink.Sink import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -18,7 +18,7 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.persistence.PersistentDataType -interface PoweredMultiblockEntity: Sink { +interface PoweredMultiblockEntity : Sink { val position: BlockKey var powerUnsafe: Int val maxPower: Int @@ -120,7 +120,7 @@ interface PoweredMultiblockEntity: Sink { if (existing.boundMultiblockEntity != null) return existing.boundMultiblockEntity = this - existing.grid.registerSink(this) + (existing.grid as PowerGrid).registerSink(this) } fun releaseInputNode() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 7629d3c3ac..48e1f93bd7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -122,24 +122,23 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM override fun onLoad() { displayHandler.update() + bindInputNode() } override fun onUnload() { displayHandler.remove() + releaseInputNode() } override fun handleRemoval() { displayHandler.remove() + releaseInputNode() } override fun displaceAdditional(movement: StarshipMovement) { displayHandler.displace(movement) } -// override fun isValid(): Boolean { -// return !removed -// } - override fun storeAdditionalData(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt index 10af6333fb..107d1b43e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt @@ -1,18 +1,18 @@ package net.horizonsend.ion.server.features.transport.grid -import net.horizonsend.ion.server.features.transport.grid.util.Sink -import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.transport.grid.sink.FluidSource -class FluidGrid(manager: WorldGridManager) : Grid(GridType.Fluid, manager) { - override fun transferResources(from: Source, to: Sink, resistanceContribution: Int, totalResistance: Int) { +class FluidGrid(manager: WorldGridManager) : Grid(GridType.Power, manager, FluidSource::class, FluidStoringEntity::class) { + override fun transferResources(from: FluidSource, to: FluidStoringEntity, resistanceContribution: Int, totalResistance: Int) { // TODO("Not yet implemented") } - override fun postMerge(other: Grid) { + override fun postMerge(other: Grid) { // TODO("Not yet implemented") } - override fun postSplit(new: List) { + override fun postSplit(new: List>) { // TODO("Not yet implemented") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt index 350a715856..52f4bcae6b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt @@ -4,16 +4,17 @@ import com.google.common.graph.ElementOrder import com.google.common.graph.GraphBuilder import com.google.common.graph.MutableGraph import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.util.Sink -import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.transport.grid.sink.Sink +import net.horizonsend.ion.server.features.transport.grid.sink.Source import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull import java.util.concurrent.ConcurrentHashMap +import kotlin.reflect.KClass @Suppress("UnstableApiUsage") -abstract class Grid(val type: GridType, val manager: WorldGridManager) { - private val sourceList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() - private val sinkList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() +abstract class Grid(val type: GridType, val manager: WorldGridManager, val source: KClass, val sink: KClass) { + private val sourceList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() + private val sinkList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() val nodes: ObjectOpenHashSet = ObjectOpenHashSet() @@ -22,7 +23,7 @@ abstract class Grid(val type: GridType, val manager: WorldGridManager) { .nodeOrder(ElementOrder.unordered()) .build() - abstract fun transferResources(from: Source, to: Sink, resistanceContribution: Int, totalResistance: Int) + abstract fun transferResources(from: Src, to: Snk, resistanceContribution: Int, totalResistance: Int) fun tickTransport() { for (source in sourceList) { @@ -32,7 +33,7 @@ abstract class Grid(val type: GridType, val manager: WorldGridManager) { } } - private fun distributeResources(source: Source, sinks: Map) { + private fun distributeResources(source: Src, sinks: Map) { val total = sinks.values.sum() for ((sink, resistance) in sinks) { @@ -43,7 +44,7 @@ abstract class Grid(val type: GridType, val manager: WorldGridManager) { /** * Finds the path between the two sources with the least resistance, and returns the resistance value. Null if no path could be found. **/ - fun getLeastResistantPath(to: Sink, from: Source): Int? { + fun getLeastResistantPath(to: Snk, from: Src): Int? { return 1 //TODO A* } @@ -52,8 +53,9 @@ abstract class Grid(val type: GridType, val manager: WorldGridManager) { nodes.add(node) graph.addNode(node) - if (node is Source) { - sourceList.add(node) + if (source.isInstance(node)) { + @Suppress("UNCHECKED_CAST") + sourceList.add(node as Src) } } @@ -70,25 +72,32 @@ abstract class Grid(val type: GridType, val manager: WorldGridManager) { } } - fun handleMerge(other: Grid) { - for (edge in other.graph.edges()) { + @Suppress("UNCHECKED_CAST") + fun cast(grid: Grid<*, *>): Grid = grid as Grid + + fun handleMerge(other: Grid<*, *>) { + val cast = cast(other) + + for (edge in cast.graph.edges()) { graph.putEdge(edge.nodeU(), edge.nodeV()) } - for (node in other.graph.nodes()) { + for (node in cast.graph.nodes()) { addNode(node) graph.addNode(node) node.grid = this } - postMerge(other) + + + postMerge(cast) } - abstract fun postMerge(other: Grid) + abstract fun postMerge(other: Grid) - abstract fun postSplit(new: List) + abstract fun postSplit(new: List>) - fun registerSource(source: Source) { + fun registerSource(source: Src) { sourceList.add(source) } @@ -96,7 +105,7 @@ abstract class Grid(val type: GridType, val manager: WorldGridManager) { sourceList.remove(source) } - fun registerSink(sink: Sink) { + fun registerSink(sink: Snk) { sinkList.add(sink) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt index 1434ff1674..b861bd0c6c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt @@ -1,16 +1,16 @@ package net.horizonsend.ion.server.features.transport.grid sealed class GridType { - abstract fun newInstance(manager: WorldGridManager): Grid + abstract fun newInstance(manager: WorldGridManager): Grid<*, *> data object Fluid : GridType() { - override fun newInstance(manager: WorldGridManager): Grid { + override fun newInstance(manager: WorldGridManager): FluidGrid { return FluidGrid(manager) } } data object Power : GridType() { - override fun newInstance(manager: WorldGridManager): Grid { + override fun newInstance(manager: WorldGridManager): PowerGrid { return PowerGrid(manager) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt index 2b1e3c6d68..48de03aed0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt @@ -1,18 +1,31 @@ package net.horizonsend.ion.server.features.transport.grid -import net.horizonsend.ion.server.features.transport.grid.util.Sink -import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.grid.sink.PowerSource +import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -class PowerGrid(manager: WorldGridManager) : Grid(GridType.Power, manager) { - override fun transferResources(from: Source, to: Sink, resistanceContribution: Int, totalResistance: Int) { -// TODO("Not yet implemented") +class PowerGrid(manager: WorldGridManager) : Grid(GridType.Power, manager, PowerSource::class, PoweredMultiblockEntity::class) { + override fun transferResources(from: PowerSource, to: PoweredMultiblockEntity, resistanceContribution: Int, totalResistance: Int) { + val share = resistanceContribution.toDouble() / totalResistance.toDouble() + + when (from) { + is PowerExtractorNode -> { + val transferPower = from.getTransferPower() * share + + } + + is SolarPanelNode -> { + + } + } } - override fun postMerge(other: Grid) { + override fun postMerge(other: Grid) { // TODO("Not yet implemented") } - override fun postSplit(new: List) { + override fun postSplit(new: List>) { // TODO("Not yet implemented") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt index c32a0f919a..b3975132ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt @@ -1,16 +1,17 @@ package net.horizonsend.ion.server.features.transport.grid +import net.horizonsend.ion.server.features.transport.grid.sink.Sink +import net.horizonsend.ion.server.features.transport.grid.sink.Source import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull -import java.lang.IndexOutOfBoundsException import java.util.concurrent.ConcurrentHashMap class WorldGridManager(val world: IonWorld) { - val allGrids = ConcurrentHashMap.newKeySet() - private val byType: ConcurrentHashMap> = ConcurrentHashMap() + val allGrids = ConcurrentHashMap.newKeySet>() + private val byType: ConcurrentHashMap, Boolean>> = ConcurrentHashMap() - private fun getGridsOfType(type: GridType): MutableSet { + private fun getGridsOfType(type: GridType): MutableSet> { return byType.getOrPut(type) { ConcurrentHashMap.newKeySet() } } @@ -26,18 +27,18 @@ class WorldGridManager(val world: IonWorld) { allGrids.forEach { it.tickTransport() } } - fun registerGrid(grid: Grid) { + fun registerGrid(grid: Grid<*, *>) { allGrids.add(grid) getGridsOfType(grid.type).add(grid) } - fun removeGrid(grid: Grid) { + fun removeGrid(grid: Grid<*, *>) { allGrids.remove(grid) getGridsOfType(grid.type).remove(grid) } @Suppress("UnstableApiUsage") - fun joinOrCreateGrid(node: TransportNode): Grid { + fun joinOrCreateGrid(node: TransportNode): Grid<*, *> { val relatedGrids = node.relationships.associateWithNotNull { val sideTwoNode = it.sideTwo.node if (!sideTwoNode.hasJoinedGrid()) return@associateWithNotNull null @@ -71,7 +72,7 @@ class WorldGridManager(val world: IonWorld) { /** * Combines the provided grid, and returns the resulting combination **/ - fun mergeGrids(others: Set): T { + fun mergeGrids(others: Set>): Grid<*, *> { when (others.size) { 0 -> throw IndexOutOfBoundsException("Attempted to merge 0 grids!") 1 -> return others.first() @@ -88,11 +89,11 @@ class WorldGridManager(val world: IonWorld) { return largest } - fun splitGrid(grid: T): List { + fun > splitGrid(grid: T): List { throw NotImplementedError() } - fun createGrid(origin: TransportNode): Grid { + fun createGrid(origin: TransportNode): Grid<*, *> { val newGrid = origin.gridType.newInstance(this) newGrid.addNode(origin) getGridsOfType(origin.gridType).add(newGrid) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt new file mode 100644 index 0000000000..f82c11e4e8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt @@ -0,0 +1,3 @@ +package net.horizonsend.ion.server.features.transport.grid.sink + +interface FluidSource : Source diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt new file mode 100644 index 0000000000..4644a4e12b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid.sink + +interface PowerSource : Source { + fun getTransferablePower(): Int +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt new file mode 100644 index 0000000000..0e00b24ab0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid.sink + +interface Sink { + fun isRequesting(): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt new file mode 100644 index 0000000000..e7ea690e2b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.grid.sink + +interface Source { + fun isProviding(): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt deleted file mode 100644 index 71859aef19..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Sink.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.util - -interface Sink { - fun isRequesting(): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt deleted file mode 100644 index eb12cb49b7..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/Source.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.util - -interface Source { - fun isProviding(): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index d2223aa087..ee0d87337b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.grid.Grid import net.horizonsend.ion.server.features.transport.grid.GridType @@ -13,6 +12,7 @@ import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ThreadLocalRandom /** @@ -23,10 +23,10 @@ abstract class TransportNode(val gridType: GridType) : PDCSerializable /** Stored relationships between nodes **/ - val relationships: MutableSet = ObjectOpenHashSet() + val relationships: MutableSet = ConcurrentHashMap.newKeySet() /** * Break all relations between this node and others diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index b8494fe96b..9f23e29267 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.grid.GridType -import net.horizonsend.ion.server.features.transport.grid.util.Source +import net.horizonsend.ion.server.features.transport.grid.sink.PowerSource import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -14,7 +14,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt -class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power), Source { +class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power), PowerSource { constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this @@ -87,6 +87,10 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(Gr return extractableNodes.mapNotNull { it.boundMultiblockEntity }.any { it.getPower() > 0 } } + override fun getTransferablePower(): Int { + return minOf(getTransferPower(), extractableNodes.sumOf { it.boundMultiblockEntity?.getPower() ?: 0 }) + } + override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index b8338e504d..f72a426580 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -29,5 +29,5 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(GridTy var boundMultiblockEntity: PoweredMultiblockEntity? = null - override fun toString(): String = "POWER INPUT NODE. Bound to $boundMultiblockEntity Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" + override fun toString(): String = "POWER INPUT NODE. Bound to $boundMultiblockEntity" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 354369c690..bcf04b4315 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -2,9 +2,9 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.grid.GridType -import net.horizonsend.ion.server.features.transport.grid.util.Source -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.grid.sink.PowerSource import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS @@ -33,7 +33,7 @@ import java.util.function.Consumer **/ class SolarPanelNode( override val manager: PowerNodeManager -) : MultiNode(GridType.Power), Source { +) : MultiNode(GridType.Power), PowerSource { /** The positions of extractors in this solar panel */ private val extractorPositions = ConcurrentHashMap.newKeySet() @@ -257,6 +257,10 @@ class SolarPanelNode( detectors?.let { detectorPositions.addAll(it.asIterable()) } } + override fun getTransferablePower(): Int { + return getPower() + } + companion object { const val POWER_PER_SECOND = 5 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 71117b2d24..ff3c0056a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -21,6 +21,8 @@ abstract class MultiNode, Z: MultiNode>(type: * from the list of contained positions, and the node is rebuilt using this method. **/ open suspend fun rebuildNode(position: BlockKey) { + grid.removeNode(this) + // Create new nodes, automatically merging together positions.forEach { addBack(it) @@ -34,6 +36,7 @@ abstract class MultiNode, Z: MultiNode>(type: // Join successor nodes to the grid positions .mapNotNullTo(mutableSetOf()) { manager.nodes[it] } + .distinct() .forEach { it.joinGrid() } } From 43659eb7a4de20d64fad597016ed319ee73f5b69 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 22:26:20 -0500 Subject: [PATCH 161/500] 2 steps back --- .../ion/server/command/admin/WorldCommand.kt | 22 ---- .../entity/type/fluids/FluidStoringEntity.kt | 22 +--- .../type/power/PoweredMultiblockEntity.kt | 20 +-- .../type/fluid/ElectrolysisMultiblock.kt | 4 - .../features/transport/grid/FluidGrid.kt | 18 --- .../server/features/transport/grid/Grid.kt | 115 ------------------ .../features/transport/grid/GridType.kt | 17 --- .../features/transport/grid/PowerGrid.kt | 31 ----- .../transport/grid/WorldGridManager.kt | 105 ---------------- .../transport/grid/sink/FluidSource.kt | 3 - .../transport/grid/sink/PowerSource.kt | 5 - .../features/transport/grid/sink/Sink.kt | 5 - .../features/transport/grid/sink/Source.kt | 5 - .../features/transport/grid/util/GraphUtil.kt | 45 ------- .../features/transport/node/TransportNode.kt | 17 +-- .../transport/node/fluid/FluidInputNode.kt | 3 +- .../transport/node/fluid/GasJunctionNode.kt | 3 +- .../transport/node/fluid/LightningRodNode.kt | 3 +- .../transport/node/general/JunctionNode.kt | 3 +- .../transport/node/general/LinearNode.kt | 3 +- .../transport/node/manager/NodeManager.kt | 6 +- .../transport/node/power/EndRodNode.kt | 3 +- .../node/power/InvertedDirectionalNode.kt | 3 +- .../node/power/PowerDirectionalNode.kt | 3 +- .../node/power/PowerEqualSplitterNode.kt | 3 +- .../node/power/PowerExtractorNode.kt | 12 +- .../transport/node/power/PowerFlowMeter.kt | 3 +- .../transport/node/power/PowerInputNode.kt | 3 +- .../transport/node/power/SolarPanelNode.kt | 14 +-- .../transport/node/power/SpongeNode.kt | 5 +- .../features/transport/node/type/MultiNode.kt | 15 +-- .../transport/node/type/SingleNode.kt | 5 +- .../ion/server/features/world/IonWorld.kt | 4 - 33 files changed, 22 insertions(+), 506 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt index 5440af2319..e8a4862486 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt @@ -12,7 +12,6 @@ import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_LIGHT_GRAY import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.common.utils.text.formatSpacePrefix -import net.horizonsend.ion.common.utils.text.join import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.command.SLCommand @@ -22,7 +21,6 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.features.world.environment.Environment import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent @@ -216,24 +214,4 @@ object WorldCommand : SLCommand() { sender.information("Entities:") sender.sendMessage(menu) } - - @Subcommand("query grids") - fun onQueryGrids(sender: Player, @Optional page: Int?) { - val manager = sender.world.ion.gridManager - val grids = manager.allGrids.toList() - - val menu = formatPaginatedMenu( - grids.size, - "/onQueryEntities", - page ?: 1 - ) { - val grid = grids[it] - - ofChildren(text(grid.javaClass.simpleName), space(), bracketed(text("${grid.manager.world.world.name}: grid, ${grid.nodes.size} nodes"))) - .hoverEvent(grid.nodes.map { node -> node.toComponent() }.join(newline())) - } - - sender.information("Grids:") - sender.sendMessage(menu) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index e944568b9e..66a963b4bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -5,9 +5,6 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.grid.FluidGrid -import net.horizonsend.ion.server.features.transport.grid.sink.Sink -import net.horizonsend.ion.server.features.transport.grid.sink.Source import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES @@ -20,7 +17,7 @@ import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER -interface FluidStoringEntity : Source, Sink { +interface FluidStoringEntity { val capacities: Array /** @@ -146,21 +143,4 @@ interface FluidStoringEntity : Source, Sink { existing.boundMultiblockEntity = null } - - /** - * Returns the grid that this multiblock is tied to - * - * Should only return null if the multiblock is partially unloaded, or not intact. - **/ - fun getFluidGrid(): FluidGrid? { - return getFluidInputNode()?.grid as? FluidGrid - } - - override fun isProviding(): Boolean { - return getStoredResources().entries.any { it.key != null && it.value > 0 } - } - - override fun isRequesting(): Boolean { - return capacities.any { it.storage.getAmount() < it.storage.getCapacity() } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index f75f82adc3..82c8f65698 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -3,8 +3,6 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.transport.grid.PowerGrid -import net.horizonsend.ion.server.features.transport.grid.sink.Sink import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -18,7 +16,7 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.persistence.PersistentDataType -interface PoweredMultiblockEntity : Sink { +interface PoweredMultiblockEntity { val position: BlockKey var powerUnsafe: Int val maxPower: Int @@ -120,7 +118,7 @@ interface PoweredMultiblockEntity : Sink { if (existing.boundMultiblockEntity != null) return existing.boundMultiblockEntity = this - (existing.grid as PowerGrid).registerSink(this) + } fun releaseInputNode() { @@ -128,19 +126,5 @@ interface PoweredMultiblockEntity : Sink { if (existing.boundMultiblockEntity != this) return existing.boundMultiblockEntity = null - existing.grid.removeSink(this) - } - - /** - * Returns the grid that this multiblock is tied to - * - * Should only return null if the multiblock is partially unloaded, or not intact. - **/ - fun getGrid(): PowerGrid? { - return getInputNode()?.grid as? PowerGrid - } - - override fun isRequesting(): Boolean { - return getPower() < maxPower } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 2705dda6e3..cc34a5bf3d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -277,10 +277,6 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock.isRequesting() || super.isRequesting() - } - companion object { const val WATER_INCREMENT = 5 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt deleted file mode 100644 index 107d1b43e0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/FluidGrid.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.transport.grid.sink.FluidSource - -class FluidGrid(manager: WorldGridManager) : Grid(GridType.Power, manager, FluidSource::class, FluidStoringEntity::class) { - override fun transferResources(from: FluidSource, to: FluidStoringEntity, resistanceContribution: Int, totalResistance: Int) { -// TODO("Not yet implemented") - } - - override fun postMerge(other: Grid) { -// TODO("Not yet implemented") - } - - override fun postSplit(new: List>) { -// TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt deleted file mode 100644 index 52f4bcae6b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/Grid.kt +++ /dev/null @@ -1,115 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import com.google.common.graph.ElementOrder -import com.google.common.graph.GraphBuilder -import com.google.common.graph.MutableGraph -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.sink.Sink -import net.horizonsend.ion.server.features.transport.grid.sink.Source -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull -import java.util.concurrent.ConcurrentHashMap -import kotlin.reflect.KClass - -@Suppress("UnstableApiUsage") -abstract class Grid(val type: GridType, val manager: WorldGridManager, val source: KClass, val sink: KClass) { - private val sourceList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() - private val sinkList: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() - - val nodes: ObjectOpenHashSet = ObjectOpenHashSet() - - val graph: MutableGraph = GraphBuilder - .undirected() - .nodeOrder(ElementOrder.unordered()) - .build() - - abstract fun transferResources(from: Src, to: Snk, resistanceContribution: Int, totalResistance: Int) - - fun tickTransport() { - for (source in sourceList) { - val sinkResistance = sinkList.associateWithNotNull { sink -> getLeastResistantPath(sink, source) } - - distributeResources(source, sinkResistance) - } - } - - private fun distributeResources(source: Src, sinks: Map) { - val total = sinks.values.sum() - - for ((sink, resistance) in sinks) { - transferResources(source, sink, resistance, total) - } - } - - /** - * Finds the path between the two sources with the least resistance, and returns the resistance value. Null if no path could be found. - **/ - fun getLeastResistantPath(to: Snk, from: Src): Int? { - return 1 //TODO A* - } - - fun addNode(node: TransportNode) { - node.grid = this - nodes.add(node) - graph.addNode(node) - - if (source.isInstance(node)) { - @Suppress("UNCHECKED_CAST") - sourceList.add(node as Src) - } - } - - fun removeNode(node: TransportNode) { - nodes.remove(node) - graph.removeNode(node) - - if (nodes.isEmpty()) { - manager.removeGrid(this) - } - - if (node is Source) { - sourceList.remove(node) - } - } - - @Suppress("UNCHECKED_CAST") - fun cast(grid: Grid<*, *>): Grid = grid as Grid - - fun handleMerge(other: Grid<*, *>) { - val cast = cast(other) - - for (edge in cast.graph.edges()) { - graph.putEdge(edge.nodeU(), edge.nodeV()) - } - - for (node in cast.graph.nodes()) { - addNode(node) - graph.addNode(node) - node.grid = this - } - - - - postMerge(cast) - } - - abstract fun postMerge(other: Grid) - - abstract fun postSplit(new: List>) - - fun registerSource(source: Src) { - sourceList.add(source) - } - - fun removeSource(source: Source) { - sourceList.remove(source) - } - - fun registerSink(sink: Snk) { - sinkList.add(sink) - } - - fun removeSink(sink: Sink) { - sinkList.remove(sink) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt deleted file mode 100644 index b861bd0c6c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/GridType.kt +++ /dev/null @@ -1,17 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -sealed class GridType { - abstract fun newInstance(manager: WorldGridManager): Grid<*, *> - - data object Fluid : GridType() { - override fun newInstance(manager: WorldGridManager): FluidGrid { - return FluidGrid(manager) - } - } - - data object Power : GridType() { - override fun newInstance(manager: WorldGridManager): PowerGrid { - return PowerGrid(manager) - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt deleted file mode 100644 index 48de03aed0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/PowerGrid.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.sink.PowerSource -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode - -class PowerGrid(manager: WorldGridManager) : Grid(GridType.Power, manager, PowerSource::class, PoweredMultiblockEntity::class) { - override fun transferResources(from: PowerSource, to: PoweredMultiblockEntity, resistanceContribution: Int, totalResistance: Int) { - val share = resistanceContribution.toDouble() / totalResistance.toDouble() - - when (from) { - is PowerExtractorNode -> { - val transferPower = from.getTransferPower() * share - - } - - is SolarPanelNode -> { - - } - } - } - - override fun postMerge(other: Grid) { -// TODO("Not yet implemented") - } - - override fun postSplit(new: List>) { -// TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt deleted file mode 100644 index b3975132ba..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/WorldGridManager.kt +++ /dev/null @@ -1,105 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid - -import net.horizonsend.ion.server.features.transport.grid.sink.Sink -import net.horizonsend.ion.server.features.transport.grid.sink.Source -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.world.IonWorld -import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull -import java.util.concurrent.ConcurrentHashMap - -class WorldGridManager(val world: IonWorld) { - val allGrids = ConcurrentHashMap.newKeySet>() - private val byType: ConcurrentHashMap, Boolean>> = ConcurrentHashMap() - - private fun getGridsOfType(type: GridType): MutableSet> { - return byType.getOrPut(type) { ConcurrentHashMap.newKeySet() } - } - - fun tickSafely() { - try { - tickTransport() - } catch (e: Throwable) { - return - } - } - - private fun tickTransport() { - allGrids.forEach { it.tickTransport() } - } - - fun registerGrid(grid: Grid<*, *>) { - allGrids.add(grid) - getGridsOfType(grid.type).add(grid) - } - - fun removeGrid(grid: Grid<*, *>) { - allGrids.remove(grid) - getGridsOfType(grid.type).remove(grid) - } - - @Suppress("UnstableApiUsage") - fun joinOrCreateGrid(node: TransportNode): Grid<*, *> { - val relatedGrids = node.relationships.associateWithNotNull { - val sideTwoNode = it.sideTwo.node - if (!sideTwoNode.hasJoinedGrid()) return@associateWithNotNull null - sideTwoNode.grid - } - - return when (relatedGrids.entries.size) { - 0 -> createGrid(node) - - 1 -> { - val (neighbor, grid) = relatedGrids.entries.first() - grid.addNode(node) - grid.graph.putEdge(neighbor.sideTwo.node, node) - - grid - } - - in 2..Int.MAX_VALUE -> { - val new = mergeGrids(relatedGrids.values.toSet()) - for (neighbor in relatedGrids.keys) { - new.graph.putEdge(neighbor.sideTwo.node, node) - } - - new - } - - else -> throw IllegalArgumentException("Negative number of grids?") - } - } - - /** - * Combines the provided grid, and returns the resulting combination - **/ - fun mergeGrids(others: Set>): Grid<*, *> { - when (others.size) { - 0 -> throw IndexOutOfBoundsException("Attempted to merge 0 grids!") - 1 -> return others.first() - } - - val largest = others.maxBy { it.nodes.size } - - for (grid in others.minus(largest)) { - largest.handleMerge(grid) - - removeGrid(grid) - } - - return largest - } - - fun > splitGrid(grid: T): List { - throw NotImplementedError() - } - - fun createGrid(origin: TransportNode): Grid<*, *> { - val newGrid = origin.gridType.newInstance(this) - newGrid.addNode(origin) - getGridsOfType(origin.gridType).add(newGrid) - - registerGrid(newGrid) - - return newGrid - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt deleted file mode 100644 index f82c11e4e8..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/FluidSource.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.sink - -interface FluidSource : Source diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt deleted file mode 100644 index 4644a4e12b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/PowerSource.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.sink - -interface PowerSource : Source { - fun getTransferablePower(): Int -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt deleted file mode 100644 index 0e00b24ab0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Sink.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.sink - -interface Sink { - fun isRequesting(): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt deleted file mode 100644 index e7ea690e2b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/sink/Source.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.sink - -interface Source { - fun isProviding(): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt deleted file mode 100644 index 3e72e383a6..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/grid/util/GraphUtil.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.horizonsend.ion.server.features.transport.grid.util - -import com.google.common.graph.Graph -import java.util.LinkedList - -@Suppress("UnstableApiUsage") -fun separateGraphs(graph: Graph): List> { - val seen: MutableSet = HashSet() - val stack = LinkedList() - val separated: MutableList> = LinkedList() - - while (true) { - var first: T? = null - - // Find next node in graph we haven't seen. - for (node in graph.nodes()) { - if (!seen.contains(node)) { - first = node - break - } - } - - // We have discovered all nodes, exit. - if (first == null) break - - // Start recursively building out all nodes in this sub-graph - val subGraph: MutableSet = HashSet() - - stack.push(first) - - while (!stack.isEmpty()) { - val entry = stack.pop() - - if (seen.contains(entry)) continue - - stack.addAll(graph.adjacentNodes(entry)) - seen.add(entry) - subGraph.add(entry) - } - - separated.add(subGraph) - } - - return separated -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index ee0d87337b..5fa1a41085 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,10 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.grid.Grid -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -18,13 +15,11 @@ import java.util.concurrent.ThreadLocalRandom /** * Represents a single node, or step, in transport transportNetwork **/ -abstract class TransportNode(val gridType: GridType) : PDCSerializable { +abstract class TransportNode() : PDCSerializable { var isDead: Boolean = false abstract val manager: NodeManager override val persistentDataType: Companion get() = Companion - lateinit var grid: Grid<*, *> - /** Stored relationships between nodes **/ val relationships: MutableSet = ConcurrentHashMap.newKeySet() @@ -106,16 +101,6 @@ abstract class TransportNode(val gridType: GridType) : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt index 72900a3770..f6ff64afce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.fluid import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -10,7 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class FluidInputNode(override val manager: FluidNodeManager) : SingleNode(GridType.Fluid) { +class FluidInputNode(override val manager: FluidNodeManager) : SingleNode() { constructor(network: FluidNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt index 4952ca30a3..38d38db91c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt @@ -1,11 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.fluid -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -class GasJunctionNode(network: FluidNodeManager) : JunctionNode(network, GridType.Fluid) { +class GasJunctionNode(network: FluidNodeManager) : JunctionNode(network) { constructor(network: FluidNodeManager, origin: BlockKey) : this(network) { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt index 64f5d14fec..793d8b35be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt @@ -1,14 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.fluid import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.block.data.Directional -class LightningRodNode(network: FluidNodeManager) : LinearNode(network, GridType.Fluid) { +class LightningRodNode(network: FluidNodeManager) : LinearNode(network) { constructor(network: FluidNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 65e3f99dce..c8e824b884 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.general -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode @@ -10,7 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -abstract class JunctionNode, B: JunctionNode>(override val manager: T, type: GridType) : MultiNode(type) { +abstract class JunctionNode, B: JunctionNode>(override val manager: T) : MultiNode() { override fun isTransferableTo(node: TransportNode): Boolean { return node !is PowerExtractorNode && node !is SolarPanelNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index 16e09feda3..94d4ce9dd0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.general import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode @@ -16,7 +15,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -abstract class LinearNode, B: LinearNode>(override val manager: T, type: GridType) : MultiNode(type) { +abstract class LinearNode, B: LinearNode>(override val manager: T) : MultiNode() { var axis by Delegates.notNull() override fun isTransferableTo(node: TransportNode): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 9f8f3d7a22..f90a2cc30f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -89,11 +89,7 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { /** * Handles any cleanup tasks at the end of loading **/ - open fun finalizeNodes() { - for ((_, node) in nodes) { - node.joinGrid() - } - } + open fun finalizeNodes() {} fun breakAllRelations() { runBlocking { nodes.values.forEach { it.clearRelations() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index ac5e94d92a..4ed87d8c76 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -1,14 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.block.data.Directional -class EndRodNode(network: PowerNodeManager) : LinearNode(network, GridType.Power) { +class EndRodNode(network: PowerNodeManager) : LinearNode(network, ) { constructor(network: PowerNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index 5a5dff047c..7a7f4f4ba9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -9,7 +8,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { +class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode() { constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index dc0cc756c5..8a5c9d4327 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -12,7 +11,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { +class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode() { private var variant: Material by Delegates.notNull() constructor(network: PowerNodeManager, position: BlockKey, variant: Material) : this(network) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index d333c28c05..ba54d688b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -9,7 +8,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class PowerEqualSplitterNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { +class PowerEqualSplitterNode(override val manager: PowerNodeManager) : SingleNode() { constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 9f23e29267..4e3cbcfbf6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.transport.grid.GridType -import net.horizonsend.ion.server.features.transport.grid.sink.PowerSource import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -14,7 +12,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt -class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power), PowerSource { +class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() { constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this @@ -83,14 +81,6 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(Gr } } - override fun isProviding(): Boolean { - return extractableNodes.mapNotNull { it.boundMultiblockEntity }.any { it.getPower() > 0 } - } - - override fun getTransferablePower(): Int { - return minOf(getTransferPower(), extractableNodes.sumOf { it.boundMultiblockEntity?.getPower() ?: 0 }) - } - override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index af777359d8..3f8ef7fc94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -7,7 +7,6 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -24,7 +23,7 @@ import org.bukkit.block.BlockFace.NORTH import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { +class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { constructor(network: PowerNodeManager, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index f72a426580..9105f2755a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -10,7 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(GridType.Power) { +class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index bcf04b4315..0edc6c7ac8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.grid.GridType -import net.horizonsend.ion.server.features.transport.grid.sink.PowerSource import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode @@ -33,7 +31,7 @@ import java.util.function.Consumer **/ class SolarPanelNode( override val manager: PowerNodeManager -) : MultiNode(GridType.Power), PowerSource { +) : MultiNode() { /** The positions of extractors in this solar panel */ private val extractorPositions = ConcurrentHashMap.newKeySet() @@ -111,10 +109,6 @@ class SolarPanelNode( return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() } - override fun isProviding(): Boolean { - return getPower() > 0 - } - /** * Calculates the light level at the detectors **/ @@ -170,8 +164,6 @@ class SolarPanelNode( override suspend fun handleRemoval(position: BlockKey) { isDead = true - grid.removeNode(this) - removePosition(position) // Remove all positions @@ -257,10 +249,6 @@ class SolarPanelNode( detectors?.let { detectorPositions.addAll(it.asIterable()) } } - override fun getTransferablePower(): Int { - return getPower() - } - companion object { const val POWER_PER_SECOND = 5 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 8826d394be..3e29efd777 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -1,8 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.transport.grid.GridType -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.general.JunctionNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -11,7 +10,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(network: PowerNodeManager) : JunctionNode(network, GridType.Power) { +class SpongeNode(network: PowerNodeManager) : JunctionNode(network) { constructor(network: PowerNodeManager, origin: BlockKey) : this(network) { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index ff3c0056a6..02ba8e448f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.type import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -10,7 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative /** * A transport node that may cover many blocks to avoid making unnecessary steps **/ -abstract class MultiNode, Z: MultiNode>(type: GridType) : TransportNode(type) { +abstract class MultiNode, Z: MultiNode> : TransportNode() { /** The positions occupied by the node **/ val positions: MutableSet = LongOpenHashSet() @@ -21,8 +20,6 @@ abstract class MultiNode, Z: MultiNode>(type: * from the list of contained positions, and the node is rebuilt using this method. **/ open suspend fun rebuildNode(position: BlockKey) { - grid.removeNode(this) - // Create new nodes, automatically merging together positions.forEach { addBack(it) @@ -32,12 +29,6 @@ abstract class MultiNode, Z: MultiNode>(type: positions.forEach { manager.nodes[it]?.buildRelations(it) } - - // Join successor nodes to the grid - positions - .mapNotNullTo(mutableSetOf()) { manager.nodes[it] } - .distinct() - .forEach { it.joinGrid() } } abstract suspend fun addBack(position: BlockKey) @@ -74,8 +65,6 @@ abstract class MultiNode, Z: MultiNode>(type: clearRelations() new.clearRelations() - grid.removeNode(this) - new.addPositions(positions) new.positions.forEach { new.buildRelations(it) } } @@ -102,8 +91,6 @@ abstract class MultiNode, Z: MultiNode>(type: override suspend fun handleRemoval(position: BlockKey) { isDead = true - grid.removeNode(this) - // Remove the position from the network manager.nodes.remove(position) // Remove the position from this node diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index fa1db29cbe..c71ce451b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.type -import net.horizonsend.ion.server.features.transport.grid.GridType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -10,7 +9,7 @@ import kotlin.properties.Delegates /** * A node that only occupies a single block **/ -abstract class SingleNode(type: GridType) : TransportNode(type) { +abstract class SingleNode : TransportNode() { var position by Delegates.notNull() override fun loadIntoNetwork() { @@ -31,13 +30,11 @@ abstract class SingleNode(type: GridType) : TransportNode(type) { override suspend fun onPlace(position: BlockKey) { buildRelations(position) - joinGrid() } override suspend fun handleRemoval(position: BlockKey) { isDead = true manager.nodes.remove(position) clearRelations() - grid.removeNode(this) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index de5c496d44..8eebf450bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.manager.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.grid.WorldGridManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.configuration.DefaultWorldConfiguration @@ -52,7 +51,6 @@ class IonWorld private constructor( val chunkRegions: MutableSet = ObjectOpenHashSet() val multiblockManager = WorldMultiblockManager(this) - val gridManager = WorldGridManager(this) /** * Gets the IonChunk at the specified coordinates if it is loaded @@ -196,8 +194,6 @@ class IonWorld private constructor( mainThreadCheck() for (ionWorld in ionWorlds.values) { - ionWorld.gridManager.tickSafely() - for (starship in ionWorld.starships) { val result = runCatching(starship::tick).exceptionOrNull() ?: continue log.warn("Exception while ticking starship!", result) From 472a054a4154e133f8f2df4fbc9eb5c327f7e732 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 11 Sep 2024 23:00:03 -0500 Subject: [PATCH 162/500] refactored power storing entities --- .../ion/server/command/qol/SetPowerCommand.kt | 2 +- .../modular/display/PowerEntityDisplay.kt | 13 +-- .../server/features/machine/AreaShields.kt | 8 +- .../entity/type/power/PowerStorage.kt | 91 +++++++++++++++++++ .../type/power/PoweredMultiblockEntity.kt | 76 ++-------------- .../type/power/UpdatedPowerDisplayEntity.kt | 9 -- .../multiblock/type/NewPoweredMultiblock.kt | 6 +- .../defense/passive/areashield/AreaShield.kt | 20 ++-- .../type/fluid/ElectrolysisMultiblock.kt | 23 ++--- .../type/power/charger/ChargerMultiblock.kt | 22 ++--- .../type/power/storage/PowerBankMultiblock.kt | 27 ++---- .../type/power/storage/PowerCellMultiblock.kt | 66 ++++++++++++-- 12 files changed, 207 insertions(+), 156 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt index 361e15a3b0..afa10b2ee1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt @@ -42,7 +42,7 @@ object SetPowerCommand : SLCommand() { val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) if (entity !is PoweredMultiblockEntity) continue - entity.setPower(amount) + entity.storage.setPower(amount) hits++ sender.debug("power sent") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt index 8bad8567bc..0b74ad86ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt @@ -2,35 +2,36 @@ package net.horizonsend.ion.server.features.client.display.modular.display import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.machine.PowerMachines.prefixComponent -import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor class PowerEntityDisplay( - private val multiblockEntity: UpdatedPowerDisplayEntity, + private val multiblockEntity: PoweredMultiblockEntity, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float, val title: Component? = null ): Display(offsetLeft, offsetUp, offsetBack, scale) { - private val updateHandler: (UpdatedPowerDisplayEntity) -> Unit = { + private val updateHandler: (PowerStorage) -> Unit = { display() } override fun register() { - multiblockEntity.displayUpdates.add(updateHandler) + multiblockEntity.storage.registerUpdateHandler(updateHandler) } override fun deRegister() { - multiblockEntity.displayUpdates.remove(updateHandler) + multiblockEntity.storage.removeUpdateHandler(updateHandler) } override fun getText(): Component { return title?.let { ofChildren(it, newline(), formatPower()) } ?: formatPower() } - private fun formatPower(): Component = ofChildren(prefixComponent, text(multiblockEntity.getPower(), NamedTextColor.GREEN)) + private fun formatPower(): Component = ofChildren(prefixComponent, text(multiblockEntity.storage.getPower(), NamedTextColor.GREEN)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index a163c8d3eb..172a4ea50e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -93,13 +93,13 @@ object AreaShields : IonServerComponent() { blockList.forEach { explosionResistanceTotal += it.type.blastResistance } for (shield in areaShields) { - var power = shield.getPower() + var power = shield.storage.getPower() if (power <= 0) continue power -= ((blockList.size.toDouble()/explosionResistanceTotal) * 10 * (this.explosionPowerOverride ?: 1.0)).toInt() - val percent = power.toFloat() / shield.maxPower.toFloat() + val percent = power.toFloat() / shield.storage.capacity.toFloat() - if (usePower) shield.setPower(power) + if (usePower) shield.storage.setPower(power) val color = Color.fromRGB( min(255f, 255 - max(0f, 255 * percent)).toInt(), @@ -125,7 +125,7 @@ object AreaShields : IonServerComponent() { val areaShields = getNearbyAreaShields(event.entity.location, 1.0) for (shield in areaShields) { - if (shield.getPower() > 0) event.isCancelled = true + if (shield.storage.getPower() > 0) event.isCancelled = true } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt new file mode 100644 index 0000000000..107eb3a399 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -0,0 +1,91 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.power + +import java.util.concurrent.ConcurrentHashMap + +class PowerStorage(amount: Int, val capacity: Int) { + private var backingPower = amount + + val mutex = Any() + + fun isEmpty() = getPower() <= 0 + fun isFull() = getPower() >= capacity + + fun setPower(amount: Int) { + synchronized(mutex) { + val correctedPower = amount.coerceIn(0, capacity) + + backingPower = correctedPower + } + + runUpdates() + } + + fun getPower(): Int { + return synchronized(mutex) { backingPower } + } + + /** + * Returns the amount of power that could not be added + **/ + fun addPower(amount: Int): Int { + val newAmount = synchronized(mutex) { + val newAmount = getPower() + amount + val corrected = newAmount.coerceIn(0, capacity) + + backingPower = corrected + newAmount + } + + runUpdates() + + return if (newAmount > capacity) capacity - newAmount else 0 + } + + /** + * Returns the amount of power that could not be removed + **/ + fun removePower(amount: Int): Int { + val newAmount = synchronized(mutex) { + val newAmount = getPower() - amount + val corrected = newAmount.coerceIn(0, capacity) + + backingPower = corrected + newAmount + } + + runUpdates() + + return if (newAmount < 0) newAmount else 0 + } + + /** + * Returns whether this multiblock has the capacity to fit the specified amount of power + **/ + fun canFitPower(amount: Int): Boolean { + return getPower() + amount < capacity + } + + /** + * Returns true if this amount of power can be removed without reaching zero. + **/ + fun canRemovePower(amount: Int): Boolean { + return getPower() - amount > 0 + } + + private val updateHandlers = ConcurrentHashMap.newKeySet<(PowerStorage) -> Unit>() + + fun registerUpdateHandler(handler: (PowerStorage) -> Unit) { + updateHandlers.add(handler) + } + + fun removeUpdateHandler(handler: (PowerStorage) -> Unit) { + updateHandlers.remove(handler) + } + + fun getUpdateHandlers(): List<(PowerStorage) -> Unit> = updateHandlers.toList() + + /** Notify update handlers of an update */ + fun runUpdates() { + getUpdateHandlers().forEach { it.invoke(this) } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 82c8f65698..e0ca6cde08 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,90 +1,28 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power -import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor -import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { - val position: BlockKey - var powerUnsafe: Int - val maxPower: Int + val multiblock: NewPoweredMultiblock<*> + val storage: PowerStorage - fun setPower(amount: Int) { - val correctedPower = amount.coerceIn(0, maxPower) - - powerUnsafe = correctedPower - - updatePowerVisually() - } - - fun isEmpty() = getPower() <= 0 - fun isFull() = getPower() >= maxPower - - fun getPower(): Int { - return powerUnsafe + fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { + return PowerStorage(data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) } - /** - * Returns the amount of power that could not be added - **/ - fun addPower(amount: Int): Int { - val newAmount = getPower() + amount - - setPower(newAmount) - - return if (newAmount > maxPower) maxPower - newAmount else 0 - } - - /** - * Returns the amount of power that could not be removed - **/ - fun removePower(amount: Int): Int { - val newAmount = getPower() - amount - - setPower(newAmount) - - return if (newAmount < 0) newAmount else 0 + fun savePowerData(store: PersistentMultiblockData) { + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, storage.getPower()) } - /** - * Returns whether this multiblock has the capacity to fit the specified amount of power - **/ - fun canFitPower(amount: Int): Boolean { - return getPower() + amount < maxPower - } - - /** - * Returns true if this amount of power can be removed without reaching zero. - **/ - fun canRemovePower(amount: Int): Boolean { - return getPower() - amount > 0 - } - - companion object { - private val prefixComponent = text("E: ", NamedTextColor.YELLOW) - } - - /** Store power data */ - fun storePower(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, powerUnsafe) - } - - fun updatePowerVisually() - - fun formatPower(): Component = ofChildren(prefixComponent, text(powerUnsafe, GREEN)) - val powerInputOffset: Vec3i fun getRealInputLocation(): Vec3i { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt deleted file mode 100644 index 87a50e137f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/UpdatedPowerDisplayEntity.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.power - -interface UpdatedPowerDisplayEntity : PoweredMultiblockEntity { - val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> - - override fun updatePowerVisually() { - displayUpdates.forEach { it.invoke(this) } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt index ad09841b6a..d6324f36d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt @@ -20,14 +20,14 @@ interface NewPoweredMultiblock : EntityMultiblock { var powerToTransfer = power * item.amount if (powerToTransfer == 0) return - val machinePower = entity.getPower() - val maxMachinePower = entity.maxPower + val machinePower = entity.storage.getPower() + val maxMachinePower = entity.storage.capacity if (maxMachinePower - machinePower < powerToTransfer) { powerToTransfer = maxMachinePower - machinePower } setPower(item, power - powerToTransfer / item.amount) - entity.addPower(powerToTransfer) + entity.storage.addPower(powerToTransfer) } companion object : SLEventListener() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index ee69baeef0..7489424a21 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -7,13 +7,13 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks @@ -24,7 +24,6 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataType.INTEGER import java.util.concurrent.TimeUnit abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { @@ -77,18 +76,19 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AreaShieldEntity { return AreaShieldEntity( + data, manager, this, x, y, z, world, - structureDirection, - data.getAdditionalDataOrDefault(POWER, INTEGER, 0) + structureDirection ) } class AreaShieldEntity( + data: PersistentMultiblockData, manager: MultiblockManager, override val multiblock: AreaShield, x: Int, @@ -96,10 +96,8 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< z: Int, world: World, signDirection: BlockFace, - override var powerUnsafe: Int, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), UpdatedPowerDisplayEntity { - override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() - override val maxPower: Int = multiblock.maxPower + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, @@ -129,11 +127,9 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< } override fun storeAdditionalData(store: PersistentMultiblockData) { - store.addAdditionalData(POWER, INTEGER, getPower()) + savePowerData(store) } - override fun toString(): String = "AREA SHIELD::: POWER:: ${getPower()}" - override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index cc34a5bf3d..fab6fde573 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -13,7 +13,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.SingleFluidStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer -import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape @@ -25,7 +26,6 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 @@ -46,7 +46,6 @@ import org.bukkit.block.data.Bisected.Half.TOP import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataType object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { override val name: String = "ElectrolysisMultiblock" @@ -177,14 +176,13 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock Unit> = mutableListOf() + override val storage: PowerStorage = loadStoredPower(data) override val capacities: Array = arrayOf( loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER)), @@ -252,7 +249,7 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock { protected abstract val tierMaterial: Material @@ -83,18 +82,19 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): ChargerEntity { return ChargerEntity( + data, manager, this, x, y, z, world, - structureDirection, - data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + structureDirection ) } class ChargerEntity( + data: PersistentMultiblockData, manager: MultiblockManager, override val multiblock: ChargerMultiblock, x: Int, @@ -102,10 +102,8 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere z: Int, world: World, signDirection: BlockFace, - override var powerUnsafe: Int - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), UpdatedPowerDisplayEntity { - override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() - override val maxPower: Int = multiblock.maxPower + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, @@ -113,7 +111,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere ).register() fun handleCharging(event: FurnaceBurnEvent, furnace: Furnace) { - val availablePower = getPower() + val availablePower = storage.getPower() if (availablePower == 0) return val item = event.fuel @@ -153,7 +151,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere powerManager.addPower(item, customItem, multiplier) - setPower(power - multiplier * item.amount) + storage.setPower(power - multiplier * item.amount) furnace.cookTime = 20.toShort() @@ -179,7 +177,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere } override fun storeAdditionalData(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) + savePowerData(store) } override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 48e1f93bd7..f19c923def 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -5,17 +5,16 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.power.UpdatedPowerDisplayEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataType abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { abstract val tierMaterial: Material @@ -90,30 +89,28 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM structureDirection: BlockFace ): PowerBankEntity { return PowerBankEntity( + data, manager, this, x, y, z, world, - structureDirection, - maxPower, - data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + structureDirection ) } class PowerBankEntity( + data: PersistentMultiblockData, manager: MultiblockManager, - multiblock: Multiblock, + override val multiblock: PowerBankMultiblock, x: Int, y: Int, z: Int, world: World, - structureDirection: BlockFace, - override val maxPower: Int, - override var powerUnsafe: Int = 0 - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), UpdatedPowerDisplayEntity { - override val displayUpdates: MutableList<(UpdatedPowerDisplayEntity) -> Unit> = mutableListOf() + structureDirection: BlockFace + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = newMultiblockSignOverlay( this, @@ -140,13 +137,9 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM } override fun storeAdditionalData(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, getPower()) + savePowerData(store) } override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) - - override fun toString(): String { - return "POWER BANK TIER: $multiblock! Power: ${getPower()}, Facing: $structureDirection" - } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 9e55891072..0f62a049b5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -1,17 +1,21 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataType -object PowerCellMultiblock : Multiblock(), PowerStoringMultiblock, EntityMultiblock { +object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "powercell" override val signText = createSignText( @@ -41,17 +45,59 @@ object PowerCellMultiblock : Multiblock(), PowerStoringMultiblock, EntityMultibl } } - override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PowerBankMultiblock.PowerBankEntity { - return PowerBankMultiblock.PowerBankEntity( + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PowerCellEntity { + return PowerCellEntity( + data, manager, this, x, y, z, world, - structureDirection, - 50_000, - data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0) + structureDirection ) } + + class PowerCellEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: PowerCellMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun onLoad() { + displayHandler.update() + bindInputNode() + } + + override fun onUnload() { + displayHandler.remove() + releaseInputNode() + } + + override fun handleRemoval() { + displayHandler.remove() + releaseInputNode() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + savePowerData(store) + } + + override val powerInputOffset: Vec3i = Vec3i(0, 0, 0) + } } From d6e5fad460b4877e6c8f9c1432dff18389ac3a41 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 12 Sep 2024 13:04:04 -0500 Subject: [PATCH 163/500] correctly bind power inputs to multiblocks --- .../type/power/PoweredMultiblockEntity.kt | 27 +++---------- .../multiblock/manager/MultiblockManager.kt | 8 ++-- .../defense/passive/areashield/AreaShield.kt | 2 + .../type/fluid/ElectrolysisMultiblock.kt | 3 ++ .../type/power/charger/ChargerMultiblock.kt | 2 + .../type/power/storage/PowerBankMultiblock.kt | 9 ++++- .../type/power/storage/PowerCellMultiblock.kt | 3 +- .../node/manager/PowerNodeManager.kt | 38 ++++++++++++++----- .../server/features/world/chunk/IonChunk.kt | 3 +- 9 files changed, 57 insertions(+), 38 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index e0ca6cde08..60b45f44cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -4,11 +4,9 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode -import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { @@ -36,31 +34,16 @@ interface PoweredMultiblockEntity { ) } - fun getInputNode(): PowerInputNode? { - this as MultiblockEntity - val block = getRealInputLocation() - - val chunk = IonChunk[world, block.x.shr(4), block.z.shr(4)] ?: return null - val manager = chunk.transportNetwork.powerNodeManager - val node = manager.getInternalNode(toBlockKey(block)) - - if (node != null) return node as? PowerInputNode - - // Try to place unregistered node - manager.manager.processBlockAddition(world.getBlockAt(block.x, block.y, block.z)) - return manager.getInternalNode(toBlockKey(block)) as? PowerInputNode - } - - fun bindInputNode() { - val existing = getInputNode() ?: return - if (existing.boundMultiblockEntity != null) return + var inputNode: PowerInputNode? - existing.boundMultiblockEntity = this + fun bindInputNode(node: PowerInputNode) { + if (node.boundMultiblockEntity != null) return + node.boundMultiblockEntity = this } fun releaseInputNode() { - val existing = getInputNode() ?: return + val existing = inputNode ?: return if (existing.boundMultiblockEntity != this) return existing.boundMultiblockEntity = null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index a2eb9db767..861482db29 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -61,6 +61,10 @@ abstract class MultiblockManager(val log: Logger) { asyncTickingMultiblockEntities[entity.locationKey] = entity } + if (entity is PoweredMultiblockEntity) { + (getNetwork(NetworkType.POWER) as PowerNodeManager).tryBindPowerNode(entity) + } + if (save) save() } @@ -123,10 +127,6 @@ abstract class MultiblockManager(val log: Logger) { // Place the entity into the chunk addMultiblockEntity(entity) - - if (entity is PoweredMultiblockEntity) { - (getNetwork(NetworkType.POWER) as PowerNodeManager).handleNewPoweredMultiblock(entity) - } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 7489424a21..1cd15477b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -97,6 +98,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< world: World, signDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + override var inputNode: PowerInputNode? = null override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index fab6fde573..711a8ced9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -26,6 +26,7 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER +import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 @@ -213,6 +214,8 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock) : NodeManager(holder) { @@ -37,13 +38,32 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho /** * Handle the addition of a new powered multiblock entity **/ - suspend fun handleNewPoweredMultiblock(new: MultiblockEntity) { + fun tryBindPowerNode(new: PoweredMultiblockEntity) { // All directions - val neighboring = getNeighborNodes(new.position, nodes, BlockFace.entries) - .filterValues { it is PowerInputNode || it is PowerExtractorNode } + val inputVec = new.getRealInputLocation() + val inputKey = toBlockKey(inputVec) - neighboring.forEach { - it.value.buildRelations(getRelative(new.locationKey, it.key)) + val inputNode = getNode(inputKey) as? PowerInputNode + + if (inputNode != null) { + new.bindInputNode(inputNode) + return + } + + val (x, y, z) = inputVec + runBlocking { + val block = getBlockIfLoaded(world, x, y, z) + if (block != null) createNodeFromBlock(block) } + + val attemptTwo = getNode(inputKey) as? PowerInputNode ?: return + + new.bindInputNode(attemptTwo) + } + + override fun finalizeNodes() { + @Suppress("UNCHECKED_CAST") + val chunk = (holder as? ChunkNetworkHolder)?.manager?.chunk ?: return + chunk.multiblockManager.getAllMultiblockEntities().values.filterIsInstance().forEach(::tryBindPowerNode) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 78e782221f..efc38364c9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -51,8 +51,9 @@ class IonChunk( // - Ore upgrader // - Explosion Reversal - val multiblockManager = ChunkMultiblockManager(this, log) + // Initialize the transport manager before the multiblock manager so that multiblocks can bind to nodes val transportNetwork: ChunkTransportManager = ChunkTransportManager(this) + val multiblockManager = ChunkMultiblockManager(this, log) /** * Logic upon loading the chunk From 6d4ec47e2bc000ec98b8af9d18a52e83820aa91c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 12 Sep 2024 13:16:10 -0500 Subject: [PATCH 164/500] fix glitch with battery input checks --- .../server/features/multiblock/type/NewPoweredMultiblock.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt index d6324f36d5..839aff77dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.registrations.legacy.CustomItems import org.bukkit.block.Sign import org.bukkit.event.EventHandler import org.bukkit.event.player.PlayerInteractEvent @@ -38,6 +39,9 @@ interface NewPoweredMultiblock : EntityMultiblock { if (multiblock !is NewPoweredMultiblock<*>) return val entity = multiblock.getMultiblockEntity(sign) ?: return + val item = event.item ?: return + if (CustomItems[item] !is CustomItems.BatteryItem) return + multiblock.handleBatteryInput(sign, entity as PoweredMultiblockEntity, event) } } From 700aae0fa22877bad37206bf981a76970b291ef0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 12 Sep 2024 13:33:40 -0500 Subject: [PATCH 165/500] mark chunk unsaved when power changes --- .../server/features/multiblock/entity/MultiblockEntity.kt | 4 ++++ .../features/multiblock/entity/type/power/PowerStorage.kt | 6 +++++- .../multiblock/entity/type/power/PoweredMultiblockEntity.kt | 2 +- .../features/multiblock/manager/ChunkMultiblockManager.kt | 5 +++++ .../server/features/multiblock/manager/MultiblockManager.kt | 2 ++ .../features/multiblock/manager/ShipMultiblockManager.kt | 1 + .../server/features/multiblock/type/NewPoweredMultiblock.kt | 1 + .../multiblock/type/power/storage/PowerBankMultiblock.kt | 6 ------ 8 files changed, 19 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 28961647f4..ca21304041 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -182,4 +182,8 @@ abstract class MultiblockEntity( return world.getBlockAt(position.x, position.y, position.z) } } + + fun markChanged() { + manager.markChanged() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index 107eb3a399..0b6fab55d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import java.util.concurrent.ConcurrentHashMap -class PowerStorage(amount: Int, val capacity: Int) { +class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacity: Int) { private var backingPower = amount val mutex = Any() @@ -17,6 +18,7 @@ class PowerStorage(amount: Int, val capacity: Int) { backingPower = correctedPower } + (holder as MultiblockEntity).markChanged() runUpdates() } @@ -36,6 +38,7 @@ class PowerStorage(amount: Int, val capacity: Int) { newAmount } + (holder as MultiblockEntity).markChanged() runUpdates() return if (newAmount > capacity) capacity - newAmount else 0 @@ -53,6 +56,7 @@ class PowerStorage(amount: Int, val capacity: Int) { newAmount } + (holder as MultiblockEntity).markChanged() runUpdates() return if (newAmount < 0) newAmount else 0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 60b45f44cc..de15f6d007 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -14,7 +14,7 @@ interface PoweredMultiblockEntity { val storage: PowerStorage fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { - return PowerStorage(data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) + return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) } fun savePowerData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index fa9c00274f..3ddfe23879 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD +import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.World import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataType @@ -24,6 +25,10 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) } + override fun markChanged() { + chunk.inner.minecraft.isUnsaved = true + } + override fun getNetwork(type: NetworkType): NodeManager { return type.get(chunk) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 861482db29..aec17cdbd5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -34,6 +34,8 @@ abstract class MultiblockManager(val log: Logger) { abstract fun save() + abstract fun markChanged() + /** * Logic upon the chunk being ticked **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 8fe667b685..14e67a6326 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -26,6 +26,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override val world get() = starship.world override fun save() {} + override fun markChanged() {} override fun getNetwork(type: NetworkType): NodeManager { return type.get(starship) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt index 839aff77dd..cd1c3f0926 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt @@ -23,6 +23,7 @@ interface NewPoweredMultiblock : EntityMultiblock { val machinePower = entity.storage.getPower() val maxMachinePower = entity.storage.capacity + if (maxMachinePower - machinePower < powerToTransfer) { powerToTransfer = maxMachinePower - machinePower } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 08ba8db05d..26ecd134b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -141,12 +141,6 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM savePowerData(store) } - override fun getRealInputLocation(): Vec3i { - val loc = super.getRealInputLocation() - println("Real input loc: $loc") - return loc - } - override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) } } From a4133e254827c6c63b128de34785b2d37a1b868b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 12 Sep 2024 14:02:31 -0500 Subject: [PATCH 166/500] mark chunk unsaved when nodes change --- .../features/transport/node/NodeFactory.kt | 2 +- .../transport/node/fluid/FluidNodeFactory.kt | 8 ++++++-- .../transport/node/manager/NodeManager.kt | 19 +++++++++++++++---- .../manager/holders/ChunkNetworkHolder.kt | 4 ++++ .../node/manager/holders/NetworkHolder.kt | 2 ++ .../node/manager/holders/ShipNetworkHolder.kt | 4 +++- .../transport/node/power/PowerNodeFactory.kt | 8 +++++--- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index 0c25ecfe6a..c36e13b0d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -8,5 +8,5 @@ abstract class NodeFactory(val network: T) { /** * Create and handle placement of a node at the position, if one should be created **/ - abstract suspend fun create(key: BlockKey, data: BlockData) + abstract suspend fun create(key: BlockKey, data: BlockData): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt index d562fc252d..27751266e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt @@ -17,8 +17,8 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional class FluidNodeFactory(network: FluidNodeManager) : NodeFactory(network) { - override suspend fun create(key: BlockKey, data: BlockData) { - if (network.nodes.contains(key)) return + override suspend fun create(key: BlockKey, data: BlockData): Boolean { + if (network.nodes.contains(key)) return false when { // Straight wires @@ -51,7 +51,11 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory println("TODO") + + else -> return false } + + return true } suspend fun addLightningRod(data: Directional, position: Long, handleRelationships: Boolean = true) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index f90a2cc30f..101d3ca2e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -27,14 +27,20 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { val previousNode = nodes[key] ?: return@launch previousNode.handleRemoval(key) + holder.markUnsaved() }} open fun processBlockRemovals(keys: Iterable) { holder.scope.launch { + var hits: Int = 0 + for (key in keys) { val previousNode = nodes[key] ?: return@launch + hits++ previousNode.handleRemoval(key) } + + if (hits > 0) holder.markUnsaved() }} open fun processBlockAddition(new: Block) { holder.scope.launch { @@ -44,22 +50,27 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { return@launch } - createNodeFromBlock(new) + if (createNodeFromBlock(new)) holder.markUnsaved() }} open fun processBlockAdditions(changed: Iterable) { holder.scope.launch { + var hits = 0 for (new in changed) { - createNodeFromBlock(new) + if (createNodeFromBlock(new)) { + hits++ + } } + + if (hits > 0) holder.markUnsaved() }} /** * Handle the creation / loading of the node into memory **/ - suspend fun createNodeFromBlock(block: Block) { + suspend fun createNodeFromBlock(block: Block): Boolean { val key = toBlockKey(block.x, block.y, block.z) - nodeFactory.create(key, block.blockData) + return nodeFactory.create(key, block.blockData) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 56c8406268..560d040843 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -179,4 +179,8 @@ class ChunkNetworkHolder private constructor (val manager: Chunk } } } + + override fun markUnsaved() { + manager.chunk.inner.minecraft.isUnsaved = true + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 8d1f707a7b..185e9893b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -33,4 +33,6 @@ interface NetworkHolder { * Method used to access nodes inside, and outside the network **/ fun getGlobalNode(key: BlockKey): TransportNode? + + fun markUnsaved() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index 1b3d614454..d39859207f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -2,8 +2,8 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World @@ -51,4 +51,6 @@ class ShipNetworkHolder(val starship: ActiveStarship) : NetworkH fun rebuildStaticNetwork() { } + + override fun markUnsaved() {/* Do nothing */} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 0930dc00df..8654984a17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -19,8 +19,8 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional class PowerNodeFactory(network: PowerNodeManager) : NodeFactory(network) { - override suspend fun create(key: BlockKey, data: BlockData) { - if (network.nodes.contains(key)) return + override suspend fun create(key: BlockKey, data: BlockData): Boolean { + if (network.nodes.contains(key)) return false when { // Straight wires @@ -73,8 +73,10 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory GateNode(this, x, y, z) - else -> return + else -> return false } + + return true } suspend fun addSponge(position: BlockKey, handleRelationships: Boolean = true) { From 2275845c851a73dcd30540359e5d14ec8df68603 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 14 Sep 2024 13:47:00 -0500 Subject: [PATCH 167/500] get world edit node mostly collection working --- .../entity/type/fluids/FluidStoringEntity.kt | 2 +- .../transport/ChunkTransportManager.kt | 27 ++++++- .../server/features/transport/IonChangeSet.kt | 54 +++++++++++++ .../features/transport/IonUpdateExtent.kt | 78 ------------------- .../features/transport/TransportManager.kt | 43 ++++++++-- .../transport/node/manager/NodeManager.kt | 44 ++++++++++- .../transport/node/power/PowerNodeFactory.kt | 2 + .../features/transport/node/type/MultiNode.kt | 4 +- .../server/features/world/chunk/IonChunk.kt | 7 ++ .../server/listener/misc/WorldEditListener.kt | 14 +--- 10 files changed, 173 insertions(+), 102 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 66a963b4bf..9f79c6bdbb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -126,7 +126,7 @@ interface FluidStoringEntity { if (node != null) return node as? FluidInputNode // Try to place unregistered node - manager.manager.processBlockAddition(world.getBlockAt(block.x, block.y, block.z)) + manager.manager.processBlockChange(world.getBlockAt(block.x, block.y, block.z)) return manager.getInternalNode(toBlockKey(block)) as? FluidInputNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt index 32dd66dc35..89d9f62f38 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.Block +import org.bukkit.block.data.BlockData class ChunkTransportManager( val chunk: IonChunk, @@ -45,15 +46,35 @@ class ChunkTransportManager( powerNodeManager.network.processBlockRemovals(keys) } - fun processBlockAddition(new: Block) { - powerNodeManager.network.processBlockAddition(new) + fun processBlockChange(new: Block) { + powerNodeManager.network.processBlockChange(new) // TODO // TODO // pipeGrid.processBlockAddition(key, new) // gasGrid.processBlockAddition(key, new) } - fun processBlockAddition(changed: Iterable) { + fun processBlockChange(position: BlockKey, data: BlockData) { + powerNodeManager.network.processBlockChange(position, data) + // TODO + // TODO +// pipeGrid.processBlockAddition(key, new) +// gasGrid.processBlockAddition(key, new) + } + + fun processBlockChanges(changeMap: Map) { + powerNodeManager.network.processBlockChanges(changeMap) + } + + fun refreshBlock(position: BlockKey) { + powerNodeManager.network.processBlockChange(position) + // TODO + // TODO +// pipeGrid.processBlockAddition(key, new) +// gasGrid.processBlockAddition(key, new) + } + + fun processBlockChange(changed: Iterable) { powerNodeManager.network.processBlockAdditions(changed) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt new file mode 100644 index 0000000000..832a08b456 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt @@ -0,0 +1,54 @@ +package net.horizonsend.ion.server.features.transport + +import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet +import com.sk89q.jnbt.CompoundTag +import com.sk89q.worldedit.bukkit.BukkitAdapter +import com.sk89q.worldedit.history.change.Change +import com.sk89q.worldedit.world.World +import com.sk89q.worldedit.world.biome.BiomeType +import com.sk89q.worldedit.world.block.BlockTypesCache +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.block.data.BlockData +import java.util.Collections + +class IonChangeSet(world: World) : AbstractChangeSet(world) { + private var counter: Int = 0 + val bukkitWorld = BukkitAdapter.adapt(world) + + override fun add(x: Int, y: Int, z: Int, combinedFrom: Int, combinedTo: Int) { + counter++ + addWriteTask { + TransportManager.handleBlockChange( + bukkitWorld, + toBlockKey(x, y, z), + BukkitAdapter.adapt(BlockTypesCache.states[combinedTo]) + ) + } + } + + private val changes = mutableMapOf() + + private var recording: Boolean = true + + override fun isRecordingChanges(): Boolean { + return recording + } + + override fun setRecordChanges(recordChanges: Boolean) { + recording = recordChanges + } + + override fun size(): Int { + return counter + } + + override fun addTileCreate(tag: CompoundTag?) {} + override fun addTileRemove(tag: CompoundTag?) {} + override fun addEntityRemove(tag: CompoundTag?) {} + override fun addEntityCreate(tag: CompoundTag?) {} + override fun addBiomeChange(x: Int, y: Int, z: Int, from: BiomeType?, to: BiomeType?) {} + override fun getIterator(redo: Boolean): MutableIterator { + return Collections.emptyIterator() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt deleted file mode 100644 index 99c47b2518..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonUpdateExtent.kt +++ /dev/null @@ -1,78 +0,0 @@ -package net.horizonsend.ion.server.features.transport - -import com.sk89q.worldedit.EditSession -import com.sk89q.worldedit.bukkit.BukkitAdapter -import com.sk89q.worldedit.extent.AbstractDelegateExtent -import com.sk89q.worldedit.extent.Extent -import com.sk89q.worldedit.function.pattern.Pattern -import com.sk89q.worldedit.math.BlockVector3 -import com.sk89q.worldedit.regions.Region -import com.sk89q.worldedit.world.block.BlockStateHolder -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.World - -class IonUpdateExtent(extent: Extent, val world: World, private val stage: EditSession.Stage) : AbstractDelegateExtent(extent) { - init { - println("Initializing ion update extent") - } - - override fun ?> setBlock(x: Int, y: Int, z: Int, block: T): Boolean { - println("Setting block 1") - println("Got extent: $stage") - - handleUpdate(BlockVector3.at(x, y, z), block) - - return extent.setBlock(x, y, z, block) - } - - @Deprecated("") - override fun ?> setBlock(position: BlockVector3, block: T): Boolean { - println("Setting block 2") - - handleUpdate(position, block) - - return extent.setBlock(position.x, position.y, position.z, block) - } - - override fun ?> setBlocks(region: Region, block: B): Int { - - println("Setting blocks 1") - return extent.setBlocks(region, block) - } - - override fun setBlocks(region: Region, pattern: Pattern): Int { - println("Setting blocks 2") - processPattern(region, pattern) - - return extent.setBlocks(region, pattern) - } - - override fun setBlocks(vset: MutableSet?, pattern: Pattern?): Int { - println("Setting blocks 3") - return extent.setBlocks(vset, pattern) - } - - private fun processPattern(region: Region, pattern: Pattern) { - val newBlocks = region.clone().mapNotNull { position -> - val newBlock = pattern.applyBlock(position) ?: return@mapNotNull null - - BukkitAdapter.adapt(newBlock) - } - -// TransportManager.handleBlockAdditions(world, newBlocks) - } - - private fun handleUpdate(position: BlockVector3, newBlock: BlockStateHolder<*>?) { - if (newBlock == null) return - - val material = BukkitAdapter.adapt(newBlock.blockType) - val blockData = BukkitAdapter.adapt(newBlock.toBaseBlock()) - - val x = position.x - val y = position.y - val z = position.z - - TransportManager.handleBlockRemoval(world, toBlockKey(x, y, z)) -// TransportManager.handleBlockAddition(world, BlockSnapshot(world, x, y, z, material, blockData)) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt index fefba76cce..eb3b4abeff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt @@ -1,15 +1,16 @@ package net.horizonsend.ion.server.features.transport -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.snapshot import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.Chunk import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.data.BlockData import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent @@ -27,20 +28,50 @@ object TransportManager : SLEventListener() { fun onBlockPlace(event: BlockPlaceEvent) { val world = event.block.world - handleBlockAddition(world, event.block) + handleBlockChange(world, event.block) } - fun handleBlockAddition(world: World, new: Block) { + fun handleBlockChange(world: World, new: Block) { val chunkX = new.x.shr(4) val chunkZ = new.z.shr(4) val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return - chunk.transportNetwork.processBlockAddition(new) + chunk.transportNetwork.processBlockChange(new) + } + + fun handleBlockChange(world: World, position: BlockKey, data: BlockData) { + val chunkX = getX(position).shr(4) + val chunkZ = getZ(position).shr(4) + + val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return + chunk.transportNetwork.processBlockChange(position, data) + } + + fun handleBlockChanges(world: World, changeMap: Map) { + val byChunk = changeMap.entries.groupBy { + Chunk.getChunkKey(getX(it.key), getZ(it.key)) + } + + for ((chunkKey, changes) in byChunk) { + val chunk = IonChunk[world, chunkKey] ?: continue + + for ((position, data) in changes) { + chunk.transportNetwork.processBlockChange(position, data) + } + } + } + + fun refreshBlock(world: World, position: BlockKey) { + val chunkX = getX(position).shr(4) + val chunkZ = getZ(position).shr(4) + + val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return + chunk.transportNetwork.refreshBlock(position) } fun handleBlockAdditions(world: World, newBlocks: Iterable) { for (new in newBlocks) { - handleBlockAddition(world, new) + handleBlockChange(world, new) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 101d3ca2e9..38ae574b79 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -7,9 +7,13 @@ import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.NamespacedKey import org.bukkit.block.Block +import org.bukkit.block.data.BlockData import org.bukkit.persistence.PersistentDataContainer import java.util.concurrent.ConcurrentHashMap @@ -43,7 +47,7 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { if (hits > 0) holder.markUnsaved() }} - open fun processBlockAddition(new: Block) { holder.scope.launch { + open fun processBlockChange(new: Block) { holder.scope.launch { if (new.type.isAir) { processBlockRemoval(toBlockKey(new.x, new.y, new.z)) @@ -53,6 +57,40 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { if (createNodeFromBlock(new)) holder.markUnsaved() }} + open fun processBlockChange(position: BlockKey) { holder.scope.launch { + val block = world.getBlockAt(getX(position), getY(position), getZ(position)) + + if (block.type.isAir) { + processBlockRemoval(position) + + return@launch + } + + if (createNodeFromBlock(block)) holder.markUnsaved() + }} + + open fun processBlockChange(position: BlockKey, data: BlockData) { holder.scope.launch { + if (data.material.isAir) { + processBlockRemoval(position) + + return@launch + } + + if (createNodeFromBlock(position, data)) holder.markUnsaved() + }} + + open fun processBlockChanges(changeMap: Map) { holder.scope.launch { + for ((position, data) in changeMap) { + if (data.material.isAir) { + processBlockRemoval(position) + + return@launch + } + + if (createNodeFromBlock(position, data)) holder.markUnsaved() + } + }} + open fun processBlockAdditions(changed: Iterable) { holder.scope.launch { var hits = 0 for (new in changed) { @@ -73,6 +111,10 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { return nodeFactory.create(key, block.blockData) } + suspend fun createNodeFromBlock(position: BlockKey, data: BlockData): Boolean { + return nodeFactory.create(position, data) + } + /** * Save additional metadata into the network PDC **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 8654984a17..ee35e2a7dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -22,6 +22,8 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory addEndRod(data as Directional, key) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 02ba8e448f..cc99ba820a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -1,17 +1,17 @@ package net.horizonsend.ion.server.features.transport.node.type -import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import java.util.concurrent.ConcurrentHashMap /** * A transport node that may cover many blocks to avoid making unnecessary steps **/ abstract class MultiNode, Z: MultiNode> : TransportNode() { /** The positions occupied by the node **/ - val positions: MutableSet = LongOpenHashSet() + val positions: MutableSet = ConcurrentHashMap.newKeySet() /** * Rebuild the node during the removal process diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index efc38364c9..d89243f978 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -159,6 +159,13 @@ class IonChunk( return world.ion.getChunk(x, z) } + /** + * Returns the chunk at the specified chunk coordinates in the world if it is loaded + **/ + operator fun get(world: World, key: Long): IonChunk? { + return world.ion.getChunk(getXFromKey(key), getZFromKey(key)) + } + fun Chunk.ion(): IonChunk = this.world.ion.getChunk(chunkKey)!! fun getXFromKey(key: Long): Int = key.toInt() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt index 65f2addd22..96747ec893 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt @@ -2,12 +2,11 @@ package net.horizonsend.ion.server.listener.misc import com.sk89q.worldedit.EditSession import com.sk89q.worldedit.WorldEdit -import com.sk89q.worldedit.bukkit.BukkitAdapter import com.sk89q.worldedit.event.Event import com.sk89q.worldedit.event.extent.EditSessionEvent import com.sk89q.worldedit.util.eventbus.Subscribe import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.transport.IonUpdateExtent +import net.horizonsend.ion.server.features.transport.IonChangeSet import org.bukkit.Bukkit object WorldEditListener : IonServerComponent(true) { @@ -22,15 +21,7 @@ object WorldEditListener : IonServerComponent(true) { registerListener(worldEdit) { event -> if (event.stage != EditSession.Stage.BEFORE_HISTORY) return@registerListener - println("Stage: ${event.stage}") - - val world = BukkitAdapter.adapt(event.world) - println("Previous extent: ${event.extent}") - println("Actor: ${event.actor}") - println("event: $event") - - event.extent = IonUpdateExtent(event.extent, world, event.stage) - println("after extent: ${event.extent}") + event.world?.let { event.extent.addPostProcessor(IonChangeSet(it)) } } } @@ -39,6 +30,7 @@ object WorldEditListener : IonServerComponent(true) { val eventClass = T::class.java @Subscribe + @Suppress("unused") // entrypoint fun onReceiveEvent(event: T) { if (eventClass.isInstance(event)) block.invoke(event as? T ?: return) } From bd8136e81749067aa52f4136545ddd628088d4ad Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 14 Sep 2024 14:03:11 -0500 Subject: [PATCH 168/500] remove node async --- .../server/features/transport/IonChangeSet.kt | 6 +-- .../features/transport/node/NodeFactory.kt | 2 +- .../transport/node/NodeRelationship.kt | 2 +- .../features/transport/node/NodeUtils.kt | 2 +- .../features/transport/node/TransportNode.kt | 14 +++--- .../transport/node/fluid/FluidInputNode.kt | 2 +- .../transport/node/fluid/FluidNodeFactory.kt | 6 +-- .../transport/node/fluid/GasJunctionNode.kt | 2 +- .../transport/node/fluid/LightningRodNode.kt | 11 +++-- .../transport/node/general/LinearNode.kt | 2 +- .../transport/node/manager/NodeManager.kt | 47 +++++++++---------- .../manager/holders/ChunkNetworkHolder.kt | 2 +- .../transport/node/power/EndRodNode.kt | 11 +++-- .../node/power/PowerExtractorNode.kt | 4 +- .../transport/node/power/PowerFlowMeter.kt | 4 +- .../transport/node/power/PowerNodeFactory.kt | 20 ++++---- .../transport/node/power/SolarPanelNode.kt | 30 ++++++------ .../transport/node/power/SpongeNode.kt | 2 +- .../features/transport/node/type/MultiNode.kt | 16 +++---- .../transport/node/type/SingleNode.kt | 6 +-- 20 files changed, 99 insertions(+), 92 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt index 832a08b456..91038dde30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt @@ -7,14 +7,12 @@ import com.sk89q.worldedit.history.change.Change import com.sk89q.worldedit.world.World import com.sk89q.worldedit.world.biome.BiomeType import com.sk89q.worldedit.world.block.BlockTypesCache -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.block.data.BlockData import java.util.Collections class IonChangeSet(world: World) : AbstractChangeSet(world) { private var counter: Int = 0 - val bukkitWorld = BukkitAdapter.adapt(world) + private val bukkitWorld = BukkitAdapter.adapt(world) override fun add(x: Int, y: Int, z: Int, combinedFrom: Int, combinedTo: Int) { counter++ @@ -27,8 +25,6 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { } } - private val changes = mutableMapOf() - private var recording: Boolean = true override fun isRecordingChanges(): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index c36e13b0d7..45ce2af840 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -8,5 +8,5 @@ abstract class NodeFactory(val network: T) { /** * Create and handle placement of a node at the position, if one should be created **/ - abstract suspend fun create(key: BlockKey, data: BlockData): Boolean + abstract fun create(key: BlockKey, data: BlockData): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 7e39a48d28..7c236d1d8c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -22,7 +22,7 @@ data class NodeRelationship( /** * Break the relation between the two nodes **/ - suspend fun breakUp() { + fun breakUp() { sideOne.node.removeRelationship(sideTwo.node) sideTwo.node.removeRelationship(sideOne.node) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index a148a4ef0e..c82d3c4940 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -36,7 +36,7 @@ fun getNeighborNodes(position: BlockKey, nodes: Collection, checkFaces * * @return the node that the provided were merged into **/ -suspend fun > handleMerges(neighbors: MutableCollection): Self { +fun > handleMerges(neighbors: MutableCollection): Self { // Get the largest neighbor val largestNeighbor = neighbors.popMaxByOrNull { it.positions.size diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 5fa1a41085..b8e35334f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -26,7 +26,7 @@ abstract class TransportNode() : PDCSerializable { override fun getPrimitiveType() = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt index f6ff64afce..ae9742eaa3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt @@ -18,7 +18,7 @@ class FluidInputNode(override val manager: FluidNodeManager) : SingleNode() { return false } - override suspend fun buildRelations(position: BlockKey) { + override fun buildRelations(position: BlockKey) { super.buildRelations(position) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt index 27751266e1..3aca3aeb19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt @@ -17,7 +17,7 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional class FluidNodeFactory(network: FluidNodeManager) : NodeFactory(network) { - override suspend fun create(key: BlockKey, data: BlockData): Boolean { + override fun create(key: BlockKey, data: BlockData): Boolean { if (network.nodes.contains(key)) return false when { @@ -58,7 +58,7 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory>(mutableListOf()) val finalNode = when (neighbors.size) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt index 38d38db91c..a71c223328 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasJunctionNode.kt @@ -9,7 +9,7 @@ class GasJunctionNode(network: FluidNodeManager) : JunctionNode, B: LinearNode< return node !is PowerExtractorNode && node !is SolarPanelNode } - override suspend fun buildRelations(position: BlockKey) { + override fun buildRelations(position: BlockKey) { for (offset in axis.faces.toList()) { val offsetKey = getRelative(position, offset, 1) val neighborNode = manager.getNode(offsetKey) ?: continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 38ae574b79..f7fd5b9fe4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.manager -import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.NodeFactory @@ -27,71 +26,71 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int - open fun processBlockRemoval(key: BlockKey) { holder.scope.launch { - val previousNode = nodes[key] ?: return@launch + open fun processBlockRemoval(key: BlockKey) { + val previousNode = nodes[key] ?: return previousNode.handleRemoval(key) holder.markUnsaved() - }} + } - open fun processBlockRemovals(keys: Iterable) { holder.scope.launch { + open fun processBlockRemovals(keys: Iterable) { var hits: Int = 0 for (key in keys) { - val previousNode = nodes[key] ?: return@launch + val previousNode = nodes[key] ?: return hits++ previousNode.handleRemoval(key) } if (hits > 0) holder.markUnsaved() - }} + } - open fun processBlockChange(new: Block) { holder.scope.launch { + open fun processBlockChange(new: Block) { if (new.type.isAir) { processBlockRemoval(toBlockKey(new.x, new.y, new.z)) - return@launch + return } if (createNodeFromBlock(new)) holder.markUnsaved() - }} + } - open fun processBlockChange(position: BlockKey) { holder.scope.launch { + open fun processBlockChange(position: BlockKey) { val block = world.getBlockAt(getX(position), getY(position), getZ(position)) if (block.type.isAir) { processBlockRemoval(position) - return@launch + return } if (createNodeFromBlock(block)) holder.markUnsaved() - }} + } - open fun processBlockChange(position: BlockKey, data: BlockData) { holder.scope.launch { + open fun processBlockChange(position: BlockKey, data: BlockData) { if (data.material.isAir) { processBlockRemoval(position) - return@launch + return } if (createNodeFromBlock(position, data)) holder.markUnsaved() - }} + } - open fun processBlockChanges(changeMap: Map) { holder.scope.launch { + open fun processBlockChanges(changeMap: Map) { for ((position, data) in changeMap) { if (data.material.isAir) { processBlockRemoval(position) - return@launch + return } if (createNodeFromBlock(position, data)) holder.markUnsaved() } - }} + } - open fun processBlockAdditions(changed: Iterable) { holder.scope.launch { + open fun processBlockAdditions(changed: Iterable) { var hits = 0 for (new in changed) { if (createNodeFromBlock(new)) { @@ -100,18 +99,18 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { } if (hits > 0) holder.markUnsaved() - }} + } /** * Handle the creation / loading of the node into memory **/ - suspend fun createNodeFromBlock(block: Block): Boolean { + fun createNodeFromBlock(block: Block): Boolean { val key = toBlockKey(block.x, block.y, block.z) return nodeFactory.create(key, block.blockData) } - suspend fun createNodeFromBlock(position: BlockKey, data: BlockData): Boolean { + fun createNodeFromBlock(position: BlockKey, data: BlockData): Boolean { return nodeFactory.create(position, data) } @@ -133,7 +132,7 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { /** * Get the neighbors of a node **/ - suspend fun buildRelations() { + fun buildRelations() { for ((key, node) in nodes) { node.buildRelations(key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 560d040843..49e2ee874a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -160,7 +160,7 @@ class ChunkNetworkHolder private constructor (val manager: Chunk * * Iterate the section for possible nodes, handle creation **/ - private suspend fun collectSectionNodes(sectionY: Int) { + private fun collectSectionNodes(sectionY: Int) { val originX = manager.chunk.originX val originY = sectionY.shl(4) - manager.chunk.inner.world.minHeight val originZ = manager.chunk.originZ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 4ed87d8c76..a1e40fede6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -1,9 +1,12 @@ package net.horizonsend.ion.server.features.transport.node.power -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.Axis import org.bukkit.block.data.Directional @@ -13,9 +16,11 @@ class EndRodNode(network: PowerNodeManager) : LinearNode(network) { - override suspend fun create(key: BlockKey, data: BlockData): Boolean { + override fun create(key: BlockKey, data: BlockData): Boolean { if (network.nodes.contains(key)) return false println("data.material ${data.material}") @@ -81,7 +81,7 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory>(mutableListOf()) val finalNode = when (neighbors.size) { @@ -100,7 +100,7 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory, Z: MultiNode> : Tran * When a position in a multi node is removed, the removed position is removed * from the list of contained positions, and the node is rebuilt using this method. **/ - open suspend fun rebuildNode(position: BlockKey) { + open fun rebuildNode(position: BlockKey) { // Create new nodes, automatically merging together positions.forEach { addBack(it) @@ -31,12 +31,12 @@ abstract class MultiNode, Z: MultiNode> : Tran } } - abstract suspend fun addBack(position: BlockKey) + abstract fun addBack(position: BlockKey) /** * Adds new a position to this node **/ - suspend fun addPosition(position: BlockKey): Self { + fun addPosition(position: BlockKey): Self { positions += position manager.nodes[position] = this @@ -49,7 +49,7 @@ abstract class MultiNode, Z: MultiNode> : Tran /** * Adds multiple positions to this node **/ - suspend fun addPositions(newPositions: Iterable) { + fun addPositions(newPositions: Iterable) { for (position in newPositions) { positions += position manager.nodes[position] = this @@ -61,7 +61,7 @@ abstract class MultiNode, Z: MultiNode> : Tran /** * Drain all the positions and connections to the provided node **/ - suspend fun drainTo(new: Self) { + fun drainTo(new: Self) { clearRelations() new.clearRelations() @@ -69,7 +69,7 @@ abstract class MultiNode, Z: MultiNode> : Tran new.positions.forEach { new.buildRelations(it) } } - override suspend fun buildRelations(position: BlockKey) { + override fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) val neighborNode = manager.getNode(offsetKey) ?: continue @@ -80,7 +80,7 @@ abstract class MultiNode, Z: MultiNode> : Tran } } - suspend fun rebuildRelations() { + fun rebuildRelations() { clearRelations() positions.forEach { @@ -88,7 +88,7 @@ abstract class MultiNode, Z: MultiNode> : Tran } } - override suspend fun handleRemoval(position: BlockKey) { + override fun handleRemoval(position: BlockKey) { isDead = true // Remove the position from the network diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index c71ce451b6..fe4544714b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -16,7 +16,7 @@ abstract class SingleNode : TransportNode() { manager.nodes[position] = this } - override suspend fun buildRelations(position: BlockKey) { + override fun buildRelations(position: BlockKey) { for (offset in ADJACENT_BLOCK_FACES) { val offsetKey = getRelative(position, offset, 1) val neighborNode = manager.getNode(offsetKey) ?: continue @@ -28,11 +28,11 @@ abstract class SingleNode : TransportNode() { } } - override suspend fun onPlace(position: BlockKey) { + override fun onPlace(position: BlockKey) { buildRelations(position) } - override suspend fun handleRemoval(position: BlockKey) { + override fun handleRemoval(position: BlockKey) { isDead = true manager.nodes.remove(position) clearRelations() From 509d07eec6c0e93eb1ded184a148fb2f7d10ac6c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 14 Sep 2024 14:04:29 -0500 Subject: [PATCH 169/500] missed println --- .../server/features/transport/node/power/PowerNodeFactory.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index b46e318aa6..b4f03e34ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -22,8 +22,6 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory addEndRod(data as Directional, key) From 691d83d80dd124d1880700c28267ec5186f61d34 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 15 Sep 2024 15:46:25 -0500 Subject: [PATCH 170/500] make node relations based on position --- .../server/command/admin/IonChunkCommand.kt | 4 +- .../transport/node/NodeRelationship.kt | 7 +- .../features/transport/node/NodeType.kt | 6 ++ .../features/transport/node/NodeUtils.kt | 60 ++++++++++++++-- .../features/transport/node/TransportNode.kt | 36 ++++++---- .../transport/node/fluid/FluidInputNode.kt | 3 + ...asJunctionNode.kt => FluidJunctionNode.kt} | 6 +- .../transport/node/fluid/FluidNodeFactory.kt | 2 +- .../transport/node/fluid/LightningRodNode.kt | 3 + .../transport/node/general/LinearNode.kt | 2 +- .../transport/node/manager/NodeManager.kt | 6 +- .../transport/node/power/EndRodNode.kt | 2 + .../node/power/InvertedDirectionalNode.kt | 3 + .../node/power/PowerDirectionalNode.kt | 2 + .../node/power/PowerEqualSplitterNode.kt | 2 + .../node/power/PowerExtractorNode.kt | 10 +-- .../transport/node/power/PowerFlowMeter.kt | 6 +- .../transport/node/power/PowerInputNode.kt | 2 + .../transport/node/power/PowerNodeFactory.kt | 5 +- .../transport/node/power/SolarPanelNode.kt | 17 ++--- .../transport/node/power/SpongeNode.kt | 3 + .../features/transport/node/type/MultiNode.kt | 70 +++++++++++++++---- .../transport/node/type/SingleNode.kt | 4 +- 23 files changed, 197 insertions(+), 64 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/{GasJunctionNode.kt => FluidJunctionNode.kt} (66%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index c491b507e9..436d0a5f45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -140,9 +140,9 @@ object IonChunkCommand : SLCommand() { @Subcommand("get node look") fun getNode(sender: Player, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { - val ionChunk = sender.chunk.ion() - val grid = network.get(ionChunk) val targeted = sender.getTargetBlock(null, 10) + val ionChunk = targeted.chunk.ion() + val grid = network.get(ionChunk) val key = toBlockKey(targeted.x, targeted.y, targeted.z) sender.information("Targeted node: ${grid.nodes[key]}") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 7c236d1d8c..f8eedb3c9a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.BlockFace /** @@ -28,15 +29,15 @@ data class NodeRelationship( } companion object { - fun create(nodeOne: TransportNode, nodeTwo: TransportNode, nodeTwoOffset: BlockFace) { + fun create(point: BlockKey, nodeOne: TransportNode, nodeTwo: TransportNode, nodeTwoOffset: BlockFace) { val canTransferTo = nodeOne.isTransferableTo(nodeTwo) val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) // Do not add the relationship if neither side can transfer if (!canTransferFrom && !canTransferTo) return - nodeOne.relationships += NodeRelationship(RelationSide(nodeOne, canTransferTo, BlockFace.SELF), RelationSide(nodeTwo, canTransferFrom, nodeTwoOffset)) - nodeTwo.relationships += NodeRelationship(RelationSide(nodeTwo, canTransferFrom, BlockFace.SELF), RelationSide(nodeOne, canTransferTo, nodeTwoOffset.oppositeFace)) + nodeOne.relationships[point] = NodeRelationship(RelationSide(nodeOne, canTransferTo, BlockFace.SELF), RelationSide(nodeTwo, canTransferFrom, nodeTwoOffset)) + nodeTwo.relationships[point] = NodeRelationship(RelationSide(nodeTwo, canTransferFrom, BlockFace.SELF), RelationSide(nodeOne, canTransferTo, nodeTwoOffset.oppositeFace)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 44ba0791f9..838086e417 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,6 +1,9 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode +import net.horizonsend.ion.server.features.transport.node.fluid.FluidJunctionNode +import net.horizonsend.ion.server.features.transport.node.fluid.LightningRodNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode @@ -25,6 +28,9 @@ enum class NodeType(val clazz: Class) { POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), //FLUID + FLUID_INPUT(FluidInputNode::class.java), + FLUID_JUNCTION(FluidJunctionNode::class.java), + LIGHTNING_ROD(LightningRodNode::class.java), //ITEM ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index c82d3c4940..bde5f72a56 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -12,8 +12,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull -import org.bukkit.World import org.bukkit.block.BlockFace +import java.util.LinkedList fun getNeighborNodes(position: BlockKey, nodes: Map, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { val x = getX(position) @@ -50,12 +50,60 @@ fun > handleMerges(neighbors: MutableCollection> separateNode(node: G): Boolean { + // Generate the grid nodes isolated from each other. + val splitGraphs: List> = separateNodePositions(node) - val chunk = IonChunk[world, x, z] ?: return null - return networkType.get(chunk).nodes[key] + if (splitGraphs.size <= 1) return false + + // Create new nodes + splitGraphs.forEach { node.ofPositions(it) } + + return true +} + +/** + * Splits a multi node's positions into multiple nodes + * https://github.com/CoFH/ThermalDynamics/blob/1.20.x/src/main/java/cofh/thermal/dynamics/common/grid/GridContainer.java#L394 + **/ +fun > separateNodePositions(node: T): List> { + val seen: MutableSet = HashSet() + val stack = LinkedList() + val separated: MutableList> = LinkedList() + + while (true) { + var first: BlockKey? = null + + // Find next node in graph we haven't seen. + for (position in node.positions) { + if (!seen.contains(position)) { + first = position + break + } + } + + // We have discovered all nodes, exit. + if (first == null) break + + // Start recursively building out all nodes in this sub-graph + val subGraph: MutableSet = HashSet() + + stack.push(first) + + while (!stack.isEmpty()) { + val entry = stack.pop() + + if (seen.contains(entry)) continue + + stack.addAll(node.adjacentPositions(entry)) + seen.add(entry) + subGraph.add(entry) + } + + separated.add(subGraph) + } + + return separated } enum class NetworkType { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index b8e35334f5..a3b6fb08e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -15,19 +15,21 @@ import java.util.concurrent.ThreadLocalRandom /** * Represents a single node, or step, in transport transportNetwork **/ -abstract class TransportNode() : PDCSerializable { +abstract class TransportNode : PDCSerializable { var isDead: Boolean = false abstract val manager: NodeManager override val persistentDataType: Companion get() = Companion /** Stored relationships between nodes **/ - val relationships: MutableSet = ConcurrentHashMap.newKeySet() + val relationships: ConcurrentHashMap = ConcurrentHashMap() + + abstract val type: NodeType /** * Break all relations between this node and others **/ fun clearRelations() { - relationships.forEach { + relationships.values.forEach { it.breakUp() } } @@ -37,22 +39,32 @@ abstract class TransportNode() : PDCSerializable> = relationships.filter { // That this node can transfer to the other - it.sideOne.transferAllowed && !it.sideTwo.node.isDead - }.map { it.sideTwo.node to it.sideOne.offset }.shuffled(ThreadLocalRandom.current()) + it.value.sideOne.transferAllowed && !it.value.sideTwo.node.isDead + }.map { it.value.sideTwo.node to it.value.sideOne.offset }.shuffled(ThreadLocalRandom.current()) /** * Store additional required data in the serialized container @@ -84,7 +96,7 @@ abstract class TransportNode() : PDCSerializable(network) { +class FluidJunctionNode(network: FluidNodeManager) : JunctionNode(network) { + override val type: NodeType = NodeType.FLUID_JUNCTION constructor(network: FluidNodeManager, origin: BlockKey) : this(network) { positions.add(origin) } @@ -17,7 +19,7 @@ class GasJunctionNode(network: FluidNodeManager) : JunctionNode GasJunctionNode(network, position).apply { loadIntoNetwork() } + 0 -> FluidJunctionNode(network, position).apply { loadIntoNetwork() } // Consolidate into neighbor 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt index 77481d7515..e22e0561e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.fluid +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -11,6 +12,8 @@ import org.bukkit.Axis import org.bukkit.block.data.Directional class LightningRodNode(network: FluidNodeManager) : LinearNode(network) { + override val type: NodeType = NodeType.LIGHTNING_ROD + constructor(network: FluidNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index e176b94356..7e9f99d5a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -29,7 +29,7 @@ abstract class LinearNode, B: LinearNode< if (this == neighborNode) continue - addRelationship(neighborNode, offset) + addRelationship(position, neighborNode, offset) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index f7fd5b9fe4..87cb33d96c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -29,18 +29,18 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { open fun processBlockRemoval(key: BlockKey) { val previousNode = nodes[key] ?: return - previousNode.handleRemoval(key) + previousNode.handlePositionRemoval(key) holder.markUnsaved() } open fun processBlockRemovals(keys: Iterable) { - var hits: Int = 0 + var hits = 0 for (key in keys) { val previousNode = nodes[key] ?: return hits++ - previousNode.handleRemoval(key) + previousNode.handlePositionRemoval(key) } if (hits > 0) holder.markUnsaved() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index a1e40fede6..f4966bcec1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.LinearNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -11,6 +12,7 @@ import org.bukkit.Axis import org.bukkit.block.data.Directional class EndRodNode(network: PowerNodeManager) : LinearNode(network, ) { + override val type: NodeType = NodeType.END_ROD_NODE constructor(network: PowerNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index 7a7f4f4ba9..71fbaeef34 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -9,6 +10,8 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode() { + override val type: NodeType = NodeType.POWER_INVERSE_DIRECTIONAL_NODE + constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index 8a5c9d4327..4f257e5509 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -12,6 +13,7 @@ import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode() { + override val type: NodeType = NodeType.POWER_DIRECTIONAL_NODE private var variant: Material by Delegates.notNull() constructor(network: PowerNodeManager, position: BlockKey, variant: Material) : this(network) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index ba54d688b8..30da958b58 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -9,6 +10,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType class PowerEqualSplitterNode(override val manager: PowerNodeManager) : SingleNode() { + override val type: NodeType = NodeType.POWER_EQUAL_SPLITTER constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 5c7ddd05d9..c04be2cbf3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -13,12 +14,13 @@ import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() { + override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this } - val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.sideTwo.node as? PowerInputNode } + val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.value.sideTwo.node as? PowerInputNode } // Region transfer /* @@ -60,9 +62,9 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() manager.extractors[position] = this } - override fun handleRemoval(position: BlockKey) { + override fun handlePositionRemoval(position: BlockKey) { manager.extractors.remove(position) - super.handleRemoval(position) + super.handlePositionRemoval(position) } override fun buildRelations(position: BlockKey) { @@ -77,7 +79,7 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() } // Add a relationship, if one should be added - addRelationship(neighborNode, offset) + addRelationship(position, neighborNode, offset) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index fb303e161d..9e1153cf59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -24,6 +25,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { + override val type: NodeType = NodeType.POWER_FLOW_METER constructor(network: PowerNodeManager, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction @@ -110,10 +112,10 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { super.onPlace(position) } - override fun handleRemoval(position: BlockKey) { + override fun handlePositionRemoval(position: BlockKey) { if (::displayHandler.isInitialized) displayHandler.remove() - super.handleRemoval(position) + super.handlePositionRemoval(position) } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index 9105f2755a..b6fc43f4e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode @@ -10,6 +11,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { + override val type: NodeType = NodeType.POWER_INPUT_NODE constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index b4f03e34ec..01331bc673 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -87,7 +87,10 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory SpongeNode(network, position).apply { loadIntoNetwork() } // Consolidate into neighbor - 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") + 1 -> { + val adjacent = neighbors.firstOrNull() + adjacent?.addPosition(position) ?: SpongeNode(network, position).apply { loadIntoNetwork() } + } // Join multiple neighbors together in 2..6 -> handleMerges(neighbors).addPosition(position) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index aae0b16a83..5bf3e06f6a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -1,7 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.power +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.separateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS @@ -33,6 +35,7 @@ import java.util.function.Consumer class SolarPanelNode( override val manager: PowerNodeManager ) : MultiNode() { + override val type: NodeType = NodeType.SOLAR_PANEL_NODE /** The positions of extractors in this solar panel */ private val extractorPositions = ConcurrentHashMap.newKeySet() @@ -162,21 +165,15 @@ class SolarPanelNode( traverseField { it.calculateExitDistance() } } - override fun handleRemoval(position: BlockKey) { + override fun handlePositionRemoval(position: BlockKey) { isDead = true removePosition(position) - // Remove all positions - positions.forEach { - manager.nodes.remove(it) + if (separateNode(this)) { + positions.clear() + clearRelations() } - - // Rebuild relations after cleared - clearRelations() - - // Rebuild the node without the lost position - rebuildNode(position) } fun addPosition(extractorKey: BlockKey, diamondKey: BlockKey, detectorKey: BlockKey): SolarPanelNode { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 924cb388df..f27e11dc43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power +import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.JunctionNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -11,6 +12,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ class SpongeNode(network: PowerNodeManager) : JunctionNode(network) { + override val type: NodeType = NodeType.SPONGE_NODE + constructor(network: PowerNodeManager, origin: BlockKey) : this(network) { positions.add(origin) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index df083cdfcd..c2bf0543b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -1,9 +1,13 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.node.separateNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import java.util.concurrent.ConcurrentHashMap /** @@ -31,8 +35,6 @@ abstract class MultiNode, Z: MultiNode> : Tran } } - abstract fun addBack(position: BlockKey) - /** * Adds new a position to this node **/ @@ -76,7 +78,7 @@ abstract class MultiNode, Z: MultiNode> : Tran if (this == neighborNode) continue - addRelationship(neighborNode, offset) + addRelationship(position, neighborNode, offset) } } @@ -88,24 +90,22 @@ abstract class MultiNode, Z: MultiNode> : Tran } } - override fun handleRemoval(position: BlockKey) { - isDead = true - + /** + * Handle the removal of a position. Slits the node if necessary + * + **/ + override fun handlePositionRemoval(position: BlockKey) { // Remove the position from the network manager.nodes.remove(position) + // Remove the position from this node positions.remove(position) + removeRelationship(position) - // Remove all positions - positions.forEach { - manager.nodes.remove(it) + if (separateNode(this)) { + positions.clear() + clearRelations() } - - // Rebuild relations after cleared - clearRelations() - - // Rebuild the node without the lost position - rebuildNode(position) } override fun loadIntoNetwork() { @@ -113,4 +113,44 @@ abstract class MultiNode, Z: MultiNode> : Tran manager.nodes[key] = this } } + + /** + * Returns the directly adjacent positions to this position that this node contains + **/ + fun adjacentPositions(key: BlockKey): Set { + return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableSetOf()) { face -> + getRelative(key, face).takeIf { positions.contains(it) } + } + } + + /** + * Places the set of positions into the network as this type of node. + **/ + fun ofPositions(positions: Set) { + @Suppress("UNCHECKED_CAST") + val newNode = type.newInstance(manager) as Self + + positions.forEach { + newNode.addPosition(it) + newNode.buildRelations(it) + } + } + + abstract fun addBack(position: BlockKey) + + open val maxPositions: Int = 32 + + open fun canAdd(position: BlockKey): Boolean { + val holder = manager.holder as? ChunkNetworkHolder<*> + if (holder != null && + (getX(position).shr(4) != holder.manager.chunk.x || + getZ(position).shr(4) != holder.manager.chunk.z) + ) return false + + return positions.size < maxPositions + } + + fun removeFromNetwork() { + positions.forEach { manager.nodes.remove(it) } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index fe4544714b..e8900935a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -24,7 +24,7 @@ abstract class SingleNode : TransportNode() { if (this == neighborNode) return // Add a relationship, if one should be added - addRelationship(neighborNode, offset) + addRelationship(position, neighborNode, offset) } } @@ -32,7 +32,7 @@ abstract class SingleNode : TransportNode() { buildRelations(position) } - override fun handleRemoval(position: BlockKey) { + override fun handlePositionRemoval(position: BlockKey) { isDead = true manager.nodes.remove(position) clearRelations() From 7860b06cb5fa2eae41298485fb59faa8288f4112 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 15 Sep 2024 18:08:42 -0500 Subject: [PATCH 171/500] make ship networks a bit better --- .../server/command/admin/IonChunkCommand.kt | 2 +- .../manager/ChunkMultiblockManager.kt | 2 +- .../multiblock/manager/MultiblockManager.kt | 4 +- .../manager/ShipMultiblockManager.kt | 2 +- ...ansportManager.kt => GlobalNodeManager.kt} | 2 +- .../server/features/transport/IonChangeSet.kt | 2 +- .../ion/server/features/transport/NewWires.kt | 20 +++++++++ .../features/transport/node/NodeFactory.kt | 2 +- .../features/transport/node/NodeType.kt | 2 +- .../features/transport/node/NodeUtils.kt | 2 +- .../features/transport/node/TransportNode.kt | 2 +- .../transport/node/fluid/FluidInputNode.kt | 2 +- .../transport/node/fluid/FluidJunctionNode.kt | 2 +- .../transport/node/fluid/FluidNodeFactory.kt | 2 +- .../transport/node/fluid/LightningRodNode.kt | 2 +- .../transport/node/general/JunctionNode.kt | 2 +- .../transport/node/general/LinearNode.kt | 2 +- .../manager}/ChunkTransportManager.kt | 42 ++++++++----------- .../node/manager/ShipTransportManager.kt | 12 ++++-- .../node/manager/TransportManager.kt | 10 +++++ .../manager/holders/ChunkNetworkHolder.kt | 4 +- .../node/manager/holders/NetworkHolder.kt | 2 +- .../node/manager/holders/ShipNetworkHolder.kt | 10 ++--- .../manager/{ => node}/FluidNodeManager.kt | 2 +- .../node/manager/{ => node}/NodeManager.kt | 2 +- .../manager/{ => node}/PowerNodeManager.kt | 2 +- .../transport/node/power/EndRodNode.kt | 2 +- .../node/power/InvertedDirectionalNode.kt | 2 +- .../node/power/PowerDirectionalNode.kt | 2 +- .../node/power/PowerEqualSplitterNode.kt | 2 +- .../node/power/PowerExtractorNode.kt | 3 +- .../transport/node/power/PowerFlowMeter.kt | 2 +- .../transport/node/power/PowerInputNode.kt | 2 +- .../transport/node/power/PowerNodeFactory.kt | 2 +- .../transport/node/power/SolarPanelNode.kt | 2 +- .../transport/node/power/SpongeNode.kt | 2 +- .../server/features/world/chunk/IonChunk.kt | 2 +- .../miscellaneous/registrations/Components.kt | 2 + .../miscellaneous/registrations/Listeners.kt | 4 +- 39 files changed, 100 insertions(+), 69 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{TransportManager.kt => GlobalNodeManager.kt} (98%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => node/manager}/ChunkTransportManager.kt (63%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/{ => node}/FluidNodeManager.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/{ => node}/NodeManager.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/{ => node}/PowerNodeManager.kt (99%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 436d0a5f45..0e44e9375a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 3ddfe23879..2543660897 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index aec17cdbd5..eff0c697b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 14e67a6326..e1f5ca357f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt index eb3b4abeff..42fe428663 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt @@ -15,7 +15,7 @@ import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent -object TransportManager : SLEventListener() { +object GlobalNodeManager : SLEventListener() { @EventHandler fun onBlockBreak(event: BlockBreakEvent) { val world = event.block.world diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt index 91038dde30..b759d49ec6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt @@ -17,7 +17,7 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { override fun add(x: Int, y: Int, z: Int, combinedFrom: Int, combinedTo: Int) { counter++ addWriteTask { - TransportManager.handleBlockChange( + GlobalNodeManager.handleBlockChange( bukkitWorld, toBlockKey(x, y, z), BukkitAdapter.adapt(BlockTypesCache.states[combinedTo]) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt new file mode 100644 index 0000000000..98b5d76979 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.transport + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +object NewWires : IonServerComponent() { + lateinit var thread: ExecutorService + + override fun onEnable() { + thread = Executors.newFixedThreadPool(128, Tasks.namedThreadFactory("wire-transport")) + } + + override fun onDisable() { + if (::thread.isInitialized) thread.shutdown() + } + + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt index 45ce2af840..58be1e9d2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.data.BlockData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 838086e417..bd66b5a926 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -4,7 +4,7 @@ import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode import net.horizonsend.ion.server.features.transport.node.fluid.FluidJunctionNode import net.horizonsend.ion.server.features.transport.node.fluid.LightningRodNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.power.PowerDirectionalNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index bde5f72a56..40718180d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index a3b6fb08e4..1d7d001b74 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt index fc5b3ced13..931a1205e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.fluid import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt index c5e46deda9..7ab825d664 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.fluid import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.JunctionNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey class FluidJunctionNode(network: FluidNodeManager) : JunctionNode(network) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt index 78f9377008..2b5df9ec7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.handleMerges -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt index e22e0561e7..758ac18968 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.fluid import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.LinearNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index c8e824b884..59412e03db 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.general import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index 7e9f99d5a6..11ccd35d96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.general import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt similarity index 63% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt index 89d9f62f38..ab24882740 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt @@ -1,80 +1,72 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.node.manager -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.Block import org.bukkit.block.data.BlockData -class ChunkTransportManager( - val chunk: IonChunk, -) { +class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { val scope = ChunkRegion.scope - val powerNodeManager = ChunkNetworkHolder(this) { PowerNodeManager(it) } + + override val powerNodeManager = ChunkNetworkHolder(this) { PowerNodeManager(it) } + override val fluidNodeManager = ChunkNetworkHolder(this) { FluidNodeManager(it) } // val pipeGrid = PowerNodeManager(this) // TODO -// val gasGrid = PowerNodeManager(this) // TODO fun setup() { powerNodeManager.handleLoad() - // TODO - // TODO + fluidNodeManager.handleLoad() } fun onUnload() { powerNodeManager.handleUnload() - // TODO - // TODO + fluidNodeManager.handleUnload() } fun save() { powerNodeManager.save(chunk.inner.persistentDataContainer.adapterContext) - // TODO - // TODO + fluidNodeManager.save(chunk.inner.persistentDataContainer.adapterContext) } fun processBlockRemoval(key: BlockKey) { powerNodeManager.network.processBlockRemoval(key) - // TODO - // TODO + fluidNodeManager.network.processBlockRemoval(key) // pipeGrid.processBlockRemoval(key) -// gasGrid.processBlockRemoval(key) } fun processBlockRemovals(keys: Iterable) { powerNodeManager.network.processBlockRemovals(keys) + fluidNodeManager.network.processBlockRemovals(keys) } fun processBlockChange(new: Block) { powerNodeManager.network.processBlockChange(new) - // TODO - // TODO + fluidNodeManager.network.processBlockChange(new) // pipeGrid.processBlockAddition(key, new) -// gasGrid.processBlockAddition(key, new) } fun processBlockChange(position: BlockKey, data: BlockData) { powerNodeManager.network.processBlockChange(position, data) - // TODO - // TODO + fluidNodeManager.network.processBlockChange(position, data) // pipeGrid.processBlockAddition(key, new) -// gasGrid.processBlockAddition(key, new) } fun processBlockChanges(changeMap: Map) { powerNodeManager.network.processBlockChanges(changeMap) + fluidNodeManager.network.processBlockChanges(changeMap) } fun refreshBlock(position: BlockKey) { powerNodeManager.network.processBlockChange(position) - // TODO - // TODO + fluidNodeManager.network.processBlockChange(position) // pipeGrid.processBlockAddition(key, new) -// gasGrid.processBlockAddition(key, new) } fun processBlockChange(changed: Iterable) { powerNodeManager.network.processBlockAdditions(changed) + fluidNodeManager.network.processBlockAdditions(changed) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index 794bc9cad7..0a7c4c535c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -2,12 +2,16 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.node.manager.holders.ShipNetworkHolder +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager + +class ShipTransportManager(val starship: Starship) : TransportManager() { + override val powerNodeManager = ShipNetworkHolder(this) { PowerNodeManager(it) } + override val fluidNodeManager = ShipNetworkHolder(this) { FluidNodeManager(it) } -class ShipTransportManager( - val starship: Starship -) { init { - load() + load() } fun load() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt new file mode 100644 index 0000000000..eafb53c3fb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.node.manager + +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager + +abstract class TransportManager { + abstract val powerNodeManager: NetworkHolder + abstract val fluidNodeManager: NetworkHolder +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 49e2ee874a..3ae2a5d4d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -5,9 +5,9 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.transport.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 185e9893b0..1fbdde9c73 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index d39859207f..e45e4036ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -1,24 +1,24 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope -import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager +import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World import kotlin.properties.Delegates -class ShipNetworkHolder(val starship: ActiveStarship) : NetworkHolder { +class ShipNetworkHolder(val manager: ShipTransportManager) : NetworkHolder { override var network: T by Delegates.notNull(); private set - constructor(manager: ActiveStarship, network: (ShipNetworkHolder) -> T) : this(manager) { + constructor(manager: ShipTransportManager, network: (ShipNetworkHolder) -> T) : this(manager) { this.network = network(this) } override val scope: CoroutineScope = ChunkRegion.scope - override fun getWorld(): World = starship.world + override fun getWorld(): World = manager.starship.world override fun handleLoad() { captureNodes() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/FluidNodeManager.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/FluidNodeManager.kt index 7c24577dc0..f681d60db9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/FluidNodeManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.manager +package net.horizonsend.ion.server.features.transport.node.manager.node import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.fluid.FluidExtractorNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt index 87cb33d96c..78047f6c43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.manager +package net.horizonsend.ion.server.features.transport.node.manager.node import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.transport.node.NetworkType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index 981cc2232c..ef0d2bda46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.manager +package net.horizonsend.ion.server.features.transport.node.manager.node import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.coroutines.runBlocking diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index f4966bcec1..5d1e627ce5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.LinearNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index 71fbaeef34..9fa0382368 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index 4f257e5509..f76e34cf53 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.power import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index 30da958b58..153316c8e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index c04be2cbf3..12cec79b13 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -15,6 +15,7 @@ import kotlin.math.roundToInt class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE + constructor(network: PowerNodeManager, position: BlockKey) : this(network) { this.position = position network.extractors[position] = this diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 9e1153cf59..3d9abdd582 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHan import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index b6fc43f4e7..dac8b2c07d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 01331bc673..9f3f0eea50 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.handleMerges -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode.Companion.matchesSolarPanelStructure import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 5bf3e06f6a..4dade4842f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.separateNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index f27e11dc43..1982f0f93a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.general.JunctionNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index d89243f978..137c012e27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.world.chunk import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.manager.ChunkMultiblockManager -import net.horizonsend.ion.server.features.transport.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.data.DataFixers import net.horizonsend.ion.server.listener.SLEventListener diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 70e9637eec..c8918c4249 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -91,6 +91,7 @@ import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeacons import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCooldown import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.Extractors +import net.horizonsend.ion.server.features.transport.NewWires import net.horizonsend.ion.server.features.transport.TransportConfig import net.horizonsend.ion.server.features.transport.Wires import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids @@ -152,6 +153,7 @@ val components: List = listOf( Pipes, Filters, Wires, + NewWires, SwordListener, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 6854f08727..d0cbd09474 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.features.progression.achievements.AchievementL import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager -import net.horizonsend.ion.server.features.transport.TransportManager +import net.horizonsend.ion.server.features.transport.GlobalNodeManager import net.horizonsend.ion.server.features.waypoint.WaypointListeners import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager @@ -84,6 +84,8 @@ val listeners: List = listOf( ActivePlayerController.Companion, TransportManager, PersonalTransporterManager, + TransportManager, + GlobalNodeManager, // Achievement Listeners AchievementListeners(), From 024e3ed365f14656f6b08b72db745c0b14e2698a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 15 Sep 2024 23:01:30 -0500 Subject: [PATCH 172/500] simplify node relationships, flood fill to find inputs --- .../starship/DeactivatedPlayerStarships.kt | 1 + .../{NewWires.kt => NewTransport.kt} | 11 ++++- .../transport/node/NodeRelationship.kt | 32 +++++---------- .../features/transport/node/TransportNode.kt | 40 +++++++++++++------ .../transport/node/fluid/FluidJunctionNode.kt | 2 +- .../transport/node/general/LinearNode.kt | 5 ++- .../node/manager/ShipTransportManager.kt | 4 ++ .../node/manager/TransportManager.kt | 4 ++ .../node/manager/node/PowerNodeManager.kt | 38 ++++++++++++++++++ .../transport/node/power/EndRodNode.kt | 3 +- .../node/power/PowerExtractorNode.kt | 17 +++++++- .../transport/node/power/PowerNodeFactory.kt | 4 +- .../transport/node/power/SolarPanelNode.kt | 7 ++-- .../transport/node/power/SpongeNode.kt | 2 +- .../miscellaneous/registrations/Components.kt | 4 +- 15 files changed, 126 insertions(+), 48 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{NewWires.kt => NewTransport.kt} (52%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt index c2ab64164a..3a9e8b3cb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/DeactivatedPlayerStarships.kt @@ -315,6 +315,7 @@ object DeactivatedPlayerStarships : IonServerComponent() { starship.subsystems.forEach { it.handleRelease() } starship.multiblockManager.releaseEntities() + starship.transportManager.release() for ((ship: StarshipData, blocks: Set) in starship.carriedShips) { if (!blocks.isEmpty()) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt similarity index 52% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 98b5d76979..bbcb9085eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewWires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -1,11 +1,14 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.transport.node.manager.TransportManager import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ExecutorService import java.util.concurrent.Executors -object NewWires : IonServerComponent() { +object NewTransport : IonServerComponent() { + private val transportManagers = ConcurrentHashMap.newKeySet() lateinit var thread: ExecutorService override fun onEnable() { @@ -16,5 +19,11 @@ object NewWires : IonServerComponent() { if (::thread.isInitialized) thread.shutdown() } + fun registerTransportManager(manager: TransportManager) { + transportManagers.add(manager) + } + fun removeTransportManager(manager: TransportManager) { + transportManagers.remove(manager) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index f8eedb3c9a..83e99add85 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -8,36 +8,26 @@ import org.bukkit.block.BlockFace * The information contains whether they may transfer to / from each other, from each side **/ data class NodeRelationship( - val sideOne: RelationSide, - val sideTwo: RelationSide + val holder: TransportNode, + val other: TransportNode, + val offset: BlockFace, + val canTransfer: Boolean ) { - /** - * A side on a node relationship - * - * @param node The node on this side of the relationship - * @param transferAllowed Whether this node is allowed to transfer to the other side - * @param nodeTwoOffset The BlockFace which this side can be found from the other side - **/ - data class RelationSide(val node: TransportNode, val transferAllowed: Boolean, val offset: BlockFace) - /** * Break the relation between the two nodes **/ fun breakUp() { - sideOne.node.removeRelationship(sideTwo.node) - sideTwo.node.removeRelationship(sideOne.node) + holder.removeRelationship(other) + other.removeRelationship(holder) } companion object { - fun create(point: BlockKey, nodeOne: TransportNode, nodeTwo: TransportNode, nodeTwoOffset: BlockFace) { - val canTransferTo = nodeOne.isTransferableTo(nodeTwo) - val canTransferFrom = nodeTwo.isTransferableTo(nodeOne) - - // Do not add the relationship if neither side can transfer - if (!canTransferFrom && !canTransferTo) return + fun create(point: BlockKey, holder: TransportNode, other: TransportNode, nodeTwoOffset: BlockFace) { + val holderToOther = holder.isTransferableTo(other) + val otherToHolder = other.isTransferableTo(holder) - nodeOne.relationships[point] = NodeRelationship(RelationSide(nodeOne, canTransferTo, BlockFace.SELF), RelationSide(nodeTwo, canTransferFrom, nodeTwoOffset)) - nodeTwo.relationships[point] = NodeRelationship(RelationSide(nodeTwo, canTransferFrom, BlockFace.SELF), RelationSide(nodeOne, canTransferTo, nodeTwoOffset.oppositeFace)) + holder.relationships[point] = NodeRelationship(holder, other, nodeTwoOffset, holderToOther) + other.relationships[point] = NodeRelationship(other, holder, nodeTwoOffset.oppositeFace, otherToHolder) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 1d7d001b74..a846d190a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -5,12 +5,12 @@ import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManag import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ThreadLocalRandom /** * Represents a single node, or step, in transport transportNetwork @@ -41,7 +41,11 @@ abstract class TransportNode : PDCSerializable> = relationships.filter { - // That this node can transfer to the other - it.value.sideOne.transferAllowed && !it.value.sideTwo.node.isDead - }.map { it.value.sideTwo.node to it.value.sideOne.offset }.shuffled(ThreadLocalRandom.current()) +// /** Gets the nodes this can transfer to **/ +// fun getTransferableNodes(): Collection> = relationships.filter { +// // That this node can transfer to the other +// it.value.holder.transferAllowed && !it.value.other.node.isDead +// }.map { it.value.other.node to it.value.holder.offset }.shuffled(ThreadLocalRandom.current()) + + /** + * Gets the distinct nodes this can transfer to + **/ + fun getTransferableNodes(): Collection { + return relationships.mapNotNullTo(mutableSetOf()) { relation -> + // The other side of the relation, only if transfer is possible between this node and it. Double check if it is dead as well + relation.value.other.takeIf { other -> relation.value.canTransfer && !other.isDead } + } + } + /** * Store additional required data in the serialized container diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt index 7ab825d664..cdb63fed04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt @@ -19,7 +19,7 @@ class FluidJunctionNode(network: FluidNodeManager) : JunctionNode, B: LinearNode< } override fun buildRelations(position: BlockKey) { + println("${javaClass.simpleName} axis: $axis faces: ${axis.faces.toList()}") for (offset in axis.faces.toList()) { val offsetKey = getRelative(position, offset, 1) val neighborNode = manager.getNode(offsetKey) ?: continue + println("neighbor: $offset ${neighborNode.javaClass.simpleName}") if (this == neighborNode) continue + println("adding relationship") addRelationship(position, neighborNode, offset) } @@ -45,5 +48,5 @@ abstract class LinearNode, B: LinearNode< persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), axis) } - override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" + override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationships.size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index 0a7c4c535c..49012601a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -18,6 +18,10 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { } + fun release() { + + } + fun displace(movement: StarshipMovement) { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt index eafb53c3fb..0b74f58935 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -7,4 +7,8 @@ import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNode abstract class TransportManager { abstract val powerNodeManager: NetworkHolder abstract val fluidNodeManager: NetworkHolder + + fun tick() { + + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index ef0d2bda46..853af23702 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NetworkType +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode @@ -15,7 +16,10 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.NamespacedKey +import java.util.LinkedList +import java.util.Queue import java.util.concurrent.ConcurrentHashMap +import kotlin.system.measureNanoTime class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER @@ -61,6 +65,40 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho new.bindInputNode(attemptTwo) } + fun tick() { + + } + + fun tickExtractor(extractorNode: PowerExtractorNode): Set { + val visitQueue: Queue = LinkedList() + val visitedSet = ObjectOpenHashSet() + val destinations = mutableSetOf() + + visitQueue.addAll(extractorNode.getTransferableNodes()) + + var transferrable = 0L + + val iterationTime = measureNanoTime { + while (visitQueue.isNotEmpty()) { + val currentNode = visitQueue.poll() + visitedSet.add(currentNode) + + if (currentNode is PowerInputNode) { + destinations.add(currentNode) + } + + transferrable += measureNanoTime { + visitQueue.addAll(currentNode.getTransferableNodes().filterNot { visitedSet.contains(it) || visitQueue.contains(it) }) + } + } + } + + println("getting next nodes time: $transferrable") + println("iterationTime: $iterationTime") + + return destinations + } + override fun finalizeNodes() { @Suppress("UNCHECKED_CAST") val chunk = (holder as? ChunkNetworkHolder)?.manager?.chunk ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt index 5d1e627ce5..60c9667ec0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt @@ -11,8 +11,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.Axis import org.bukkit.block.data.Directional -class EndRodNode(network: PowerNodeManager) : LinearNode(network, ) { +class EndRodNode(network: PowerNodeManager) : LinearNode(network) { override val type: NodeType = NodeType.END_ROD_NODE + constructor(network: PowerNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) this.axis = axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index 12cec79b13..e9b0c20b55 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager @@ -9,9 +10,12 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt +import kotlin.system.measureNanoTime class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE @@ -21,7 +25,7 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() network.extractors[position] = this } - val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.value.sideTwo.node as? PowerInputNode } + val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.value.other as? PowerInputNode } // Region transfer /* @@ -84,6 +88,15 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() } } - override fun toString(): String = "POWER Extractor NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes" + override fun toString(): String { + val destinations: Set + val time = measureNanoTime { + destinations = manager.tickExtractor(this) + } + + debugAudience.highlightBlocks(destinations.map { toVec3i(it.position) }, 50L) + + return "Extractor. found ${destinations.size} in $time ns" + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt index 9f3f0eea50..1f116ab676 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt @@ -84,7 +84,7 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory SpongeNode(network, position).apply { loadIntoNetwork() } + 0 -> SpongeNode(network, position).addPosition(position) // Consolidate into neighbor 1 -> { @@ -112,7 +112,7 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory EndRodNode(network, position, data.facing.axis).apply { loadIntoNetwork() } + 0 -> EndRodNode(network, position, data.facing.axis).addPosition(position) // Consolidate into neighbor 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 4dade4842f..f331ef4317 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -14,7 +14,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.firsts import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded @@ -64,12 +63,12 @@ class SolarPanelNode( val neighbors = getTransferableNodes() // Transferable node provides an exit - if (neighbors.any { it.first !is SolarPanelNode }) { + if (neighbors.any { it !is SolarPanelNode }) { exitDistance = 0 return } - val solars = neighbors.firsts().filterIsInstance() + val solars = neighbors.filterIsInstance() if (solars.isEmpty()) { exitDistance = -1 return @@ -262,5 +261,5 @@ class SolarPanelNode( } } - override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().firsts().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance, powerRatio = ${getPowerRatio()}, location = ${toVec3i(positions.random())}" + override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance, powerRatio = ${getPowerRatio()}, location = ${toVec3i(positions.random())}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt index 1982f0f93a..e07c8fc7c5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt @@ -22,5 +22,5 @@ class SpongeNode(network: PowerNodeManager) : JunctionNode = listOf( Pipes, Filters, Wires, - NewWires, + NewTransport, SwordListener, From 88215de33d9434604013055b25a123478be85a21 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 15 Sep 2024 23:35:04 -0500 Subject: [PATCH 173/500] performance improvements --- .../transport/node/NodeRelationship.kt | 4 +++ .../features/transport/node/TransportNode.kt | 22 +++++++------- .../transport/node/general/LinearNode.kt | 3 -- .../node/manager/node/PowerNodeManager.kt | 30 ++++++------------- 4 files changed, 23 insertions(+), 36 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 83e99add85..258a270a61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -19,6 +19,8 @@ data class NodeRelationship( fun breakUp() { holder.removeRelationship(other) other.removeRelationship(holder) + holder.refreshTransferCache() + other.refreshTransferCache() } companion object { @@ -28,6 +30,8 @@ data class NodeRelationship( holder.relationships[point] = NodeRelationship(holder, other, nodeTwoOffset, holderToOther) other.relationships[point] = NodeRelationship(other, holder, nodeTwoOffset.oppositeFace, otherToHolder) + holder.refreshTransferCache() + other.refreshTransferCache() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index a846d190a1..e4ae391ae4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManag import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer @@ -42,10 +41,7 @@ abstract class TransportNode : PDCSerializable> = relationships.filter { -// // That this node can transfer to the other -// it.value.holder.transferAllowed && !it.value.other.node.isDead -// }.map { it.value.other.node to it.value.holder.offset }.shuffled(ThreadLocalRandom.current()) + var cachedTransferable: Collection = ArrayDeque(getTransferableNodes()) + + fun refreshTransferCache() { + cachedTransferable = ArrayDeque(getTransferableNodes()) + } /** * Gets the distinct nodes this can transfer to diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index 1e9af4b86b..ed0ffe7c99 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -23,14 +23,11 @@ abstract class LinearNode, B: LinearNode< } override fun buildRelations(position: BlockKey) { - println("${javaClass.simpleName} axis: $axis faces: ${axis.faces.toList()}") for (offset in axis.faces.toList()) { val offsetKey = getRelative(position, offset, 1) val neighborNode = manager.getNode(offsetKey) ?: continue - println("neighbor: $offset ${neighborNode.javaClass.simpleName}") if (this == neighborNode) continue - println("adding relationship") addRelationship(position, neighborNode, offset) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index 853af23702..34c280182b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -16,10 +16,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.NamespacedKey -import java.util.LinkedList -import java.util.Queue import java.util.concurrent.ConcurrentHashMap -import kotlin.system.measureNanoTime class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER @@ -70,31 +67,22 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } fun tickExtractor(extractorNode: PowerExtractorNode): Set { - val visitQueue: Queue = LinkedList() + val visitQueue = ArrayDeque() val visitedSet = ObjectOpenHashSet() - val destinations = mutableSetOf() + val destinations = ObjectOpenHashSet() visitQueue.addAll(extractorNode.getTransferableNodes()) - var transferrable = 0L + while (visitQueue.isNotEmpty()) { + val currentNode = visitQueue.removeFirst() + visitedSet.add(currentNode) - val iterationTime = measureNanoTime { - while (visitQueue.isNotEmpty()) { - val currentNode = visitQueue.poll() - visitedSet.add(currentNode) - - if (currentNode is PowerInputNode) { - destinations.add(currentNode) - } - - transferrable += measureNanoTime { - visitQueue.addAll(currentNode.getTransferableNodes().filterNot { visitedSet.contains(it) || visitQueue.contains(it) }) - } + if (currentNode is PowerInputNode) { + destinations.add(currentNode) } - } - println("getting next nodes time: $transferrable") - println("iterationTime: $iterationTime") + visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) + } return destinations } From 94c2887226d6578968559bd0725b11372af5e31b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 16 Sep 2024 01:00:29 -0500 Subject: [PATCH 174/500] temporary transfer code --- .../ion/server/features/starship/Starship.kt | 1 + .../server/features/transport/Extractors.kt | 1 + .../features/transport/node/TransportNode.kt | 4 +- .../node/manager/TransportManager.kt | 2 +- .../manager/holders/ChunkNetworkHolder.kt | 5 ++ .../node/manager/holders/NetworkHolder.kt | 3 ++ .../node/manager/holders/ShipNetworkHolder.kt | 5 ++ .../node/manager/node/PowerNodeManager.kt | 46 +++++++++++++++---- .../node/power/PowerExtractorNode.kt | 20 ++++---- .../transport/node/power/PowerInputNode.kt | 14 ++++++ .../transport/node/power/SolarPanelNode.kt | 2 + .../server/features/world/chunk/IonChunk.kt | 4 +- 12 files changed, 80 insertions(+), 27 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index e828e0c665..f0952d3c5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -141,6 +141,7 @@ class Starship( fun tick() { controller.tick() multiblockManager.tick() + transportManager.tick() subsystems.forEach { it.tick() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt index c273a58819..f51b4c246e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt @@ -50,6 +50,7 @@ object Extractors : IonServerComponent() { val BUSY_PIPE_EXTRACTORS: MutableSet = ConcurrentHashMap.newKeySet() override fun onEnable() { + return IonServer.server.worlds.forEach(Extractors::loadExtractors) Tasks.asyncRepeat(20 * 2, 20 * 2) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index e4ae391ae4..c9cb2eb1bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -51,9 +51,7 @@ abstract class TransportNode : PDCSerializable fun tick() { - + powerNodeManager.network.tick() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 3ae2a5d4d6..afd0547acc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -5,6 +5,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager @@ -183,4 +184,8 @@ class ChunkNetworkHolder private constructor (val manager: Chunk override fun markUnsaved() { manager.chunk.inner.minecraft.isUnsaved = true } + + override fun getMultiblockManager(): MultiblockManager { + return manager.chunk.multiblockManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 1fbdde9c73..4fb2dd15ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -35,4 +36,6 @@ interface NetworkHolder { fun getGlobalNode(key: BlockKey): TransportNode? fun markUnsaved() + + abstract fun getMultiblockManager(): MultiblockManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index e45e4036ba..aa2758fb05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager @@ -53,4 +54,8 @@ class ShipNetworkHolder(val manager: ShipTransportManager) : Net } override fun markUnsaved() {/* Do nothing */} + + override fun getMultiblockManager(): MultiblockManager { + return manager.starship.multiblockManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index 34c280182b..b8b4a6c60e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.manager.node import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.TransportNode @@ -17,6 +16,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap +import kotlin.math.roundToInt class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER @@ -52,10 +52,8 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } val (x, y, z) = inputVec - runBlocking { - val block = getBlockIfLoaded(world, x, y, z) - if (block != null) createNodeFromBlock(block) - } + val block = getBlockIfLoaded(world, x, y, z) + if (block != null) createNodeFromBlock(block) val attemptTwo = getNode(inputKey) as? PowerInputNode ?: return @@ -63,22 +61,50 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } fun tick() { + extractors.values.forEach(::tickExtractor) + solarPanels.forEach(::tickSolarPanel) + } + + fun tickExtractor(extractorNode: PowerExtractorNode) { + val availablePower = extractorNode.getTransferPower() + if (availablePower == 0) return + val destinations = getNetworkDestinations(extractorNode) + val share = availablePower.toDouble() / destinations.size.toDouble() + + for (destination in destinations) { + destination.storage.addPower(share.roundToInt()) + } + } + + fun tickSolarPanel(panelNode: SolarPanelNode) { + val powerCheck = panelNode.getPower() + if (powerCheck == 0) return + + val destinations = getNetworkDestinations(panelNode) + val realPower = panelNode.tickAndGetPower() + val share = realPower.toDouble() / destinations.size.toDouble() + + println("Sending $realPower to ${destinations.size} destinations") + + for (destination in destinations) { + destination.storage.addPower(share.roundToInt()) + } } - fun tickExtractor(extractorNode: PowerExtractorNode): Set { + private fun getNetworkDestinations(origin: TransportNode): ObjectOpenHashSet { val visitQueue = ArrayDeque() val visitedSet = ObjectOpenHashSet() - val destinations = ObjectOpenHashSet() + val destinations = ObjectOpenHashSet() - visitQueue.addAll(extractorNode.getTransferableNodes()) + visitQueue.addAll(origin.getTransferableNodes()) while (visitQueue.isNotEmpty()) { val currentNode = visitQueue.removeFirst() visitedSet.add(currentNode) - if (currentNode is PowerInputNode) { - destinations.add(currentNode) + if (currentNode is PowerInputNode && currentNode.isCalling()) { + destinations.add(currentNode.boundMultiblockEntity) } visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index e9b0c20b55..cc849ad8e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.power import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager @@ -10,12 +9,9 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt -import kotlin.system.measureNanoTime class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE @@ -89,14 +85,14 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() } override fun toString(): String { - val destinations: Set - val time = measureNanoTime { - destinations = manager.tickExtractor(this) - } - - debugAudience.highlightBlocks(destinations.map { toVec3i(it.position) }, 50L) - - return "Extractor. found ${destinations.size} in $time ns" +// val destinations: Set +// val time = measureNanoTime { +// destinations = manager.tickExtractor(this) +// } +// +// debugAudience.highlightBlocks(destinations.map { toVec3i(it.position) }, 50L) + + return "Extractor. found"// ${destinations.size} in $time ns" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index dac8b2c07d..bfd95cd733 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -30,5 +30,19 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { var boundMultiblockEntity: PoweredMultiblockEntity? = null + fun isCalling(): Boolean = boundMultiblockEntity != null && !(boundMultiblockEntity?.storage?.isFull() ?: false) + + override fun onPlace(position: BlockKey) { + super.onPlace(position) + +// getNearbyPowerInputs().forEach { manager.tryBindPowerNode(it) } + } + +// fun getNearbyPowerInputs(): Collection { +// return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableSetOf()) { +// manager.holder.getMultiblockManager()[getRelative(position, it)] as? PoweredMultiblockEntity +// } +// } + override fun toString(): String = "POWER INPUT NODE. Bound to $boundMultiblockEntity" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index f331ef4317..4ca693424d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -45,6 +45,8 @@ class SolarPanelNode( private val cellNumber: Int get() = extractorPositions.size override fun isTransferableTo(node: TransportNode): Boolean { + if (node is SolarPanelNode && node.exitDistance > this.exitDistance) return false + // Solar panels should be able to transfer through extractors and other solar panels return node !is PowerExtractorNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 137c012e27..d2e5473f61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -82,7 +82,9 @@ class IonChunk( /** * Logic upon world tick **/ - fun tick() {} + fun tick() { + transportNetwork.tick() + } /** * Gets the neighboring chunk in this direction From 3971b1cde81c19a696faaa24bd42bc8d8a403ce4 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 17 Sep 2024 01:28:48 -0500 Subject: [PATCH 175/500] slightly more permanent power transfer code --- .../node/manager/node/PowerNodeManager.kt | 198 ++++++++++++++++-- .../features/world/chunk/ChunkRegion.kt | 6 +- 2 files changed, 184 insertions(+), 20 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index b8b4a6c60e..8e3e5d40cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -6,17 +6,24 @@ import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap import kotlin.math.roundToInt +import kotlin.system.measureNanoTime class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER @@ -66,36 +73,43 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } fun tickExtractor(extractorNode: PowerExtractorNode) { - val availablePower = extractorNode.getTransferPower() - if (availablePower == 0) return + val powerCheck = extractorNode.getTransferPower() + if (powerCheck == 0) return + val destinations: ObjectOpenHashSet - val destinations = getNetworkDestinations(extractorNode) - val share = availablePower.toDouble() / destinations.size.toDouble() + val floodFillTime: Long + val transferTime: Long + val fullTransferTime = measureNanoTime { + floodFillTime = measureNanoTime { destinations = getNetworkDestinations(extractorNode) } - for (destination in destinations) { - destination.storage.addPower(share.roundToInt()) + extractorNode.markTicked() + transferTime = measureNanoTime { runPowerTransfer(extractorNode, destinations.toList(), extractorNode.getTransferPower()) } } + + + println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") } fun tickSolarPanel(panelNode: SolarPanelNode) { val powerCheck = panelNode.getPower() if (powerCheck == 0) return + val destinations: ObjectOpenHashSet - val destinations = getNetworkDestinations(panelNode) - val realPower = panelNode.tickAndGetPower() - val share = realPower.toDouble() / destinations.size.toDouble() - - println("Sending $realPower to ${destinations.size} destinations") + val floodFillTime: Long + val transferTime: Long + val fullTransferTime = measureNanoTime { + floodFillTime = measureNanoTime { destinations = getNetworkDestinations(panelNode) } - for (destination in destinations) { - destination.storage.addPower(share.roundToInt()) + transferTime = measureNanoTime { runPowerTransfer(panelNode, destinations.toList(), panelNode.tickAndGetPower()) } } + + println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") } - private fun getNetworkDestinations(origin: TransportNode): ObjectOpenHashSet { + private fun getNetworkDestinations(origin: TransportNode): ObjectOpenHashSet { val visitQueue = ArrayDeque() val visitedSet = ObjectOpenHashSet() - val destinations = ObjectOpenHashSet() + val destinations = ObjectOpenHashSet() visitQueue.addAll(origin.getTransferableNodes()) @@ -104,7 +118,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho visitedSet.add(currentNode) if (currentNode is PowerInputNode && currentNode.isCalling()) { - destinations.add(currentNode.boundMultiblockEntity) + destinations.add(currentNode) } visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) @@ -113,6 +127,158 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho return destinations } + /** + * Runs the power transfer fr + **/ + fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int) { + if (destinations.isEmpty()) return + println("Sending $availableTransferPower to ${destinations.size} destinations") + + val numDestinations = destinations.size + + var maximumResistance: Double = -1.0 + + val paths: Array?> = Array(numDestinations) { runCatching { getPath(source, destinations[it]) }.getOrNull() } + + // Perform the calc & max find in the same loop + val pathResistance: Array = Array(numDestinations) { + val res = calculatePathResistance(paths[it]) + if (res != null && maximumResistance < res) maximumResistance = res + + res + } + + // All null, no paths found + if (maximumResistance == -1.0) return + + var shareSum = 0.0 + + val shareFactors: Array = Array(numDestinations) { index -> + val resistance = pathResistance[index] ?: return@Array null + val fac = (numDestinations - index).toDouble() / (resistance / maximumResistance) + shareSum += fac + + fac + } + + for ((index, destination) in destinations.withIndex()) { + val shareFactor = shareFactors[index] ?: return + val share = shareFactor / shareSum + + val sent = availableTransferPower * share // TODO more complex transfer code + + paths[index]?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(sent.roundToInt()) } + destination.boundMultiblockEntity?.storage?.addPower(sent.toInt()) + } + } + + fun calculatePathResistance(path: List?): Double? { + if (path == null) return null + + return 1.0 + } + + /** + * Uses the A* algorithm to find the shortest available path between these two nodes. + **/ + private fun getPath(from: TransportNode, to: TransportNode): List? { + val queue = ArrayDeque(1) + queue.add(NodeContainer(from, null, 0, getHeuristic(from, to))) + + val visited = mutableListOf() + + var iterations = 0 + + while (queue.isNotEmpty() && iterations < 150) { + iterations++ + val current = queue.minBy { it.f } + + if (current.node == to) { + return current.collectPath() + } + + queue.remove(current) + visited.add(current) + + for (neighbor in getNeighbors(current)) { + if (visited.contains(neighbor)) continue + neighbor.f = neighbor.g + getHeuristic(neighbor.node, to) + + val existingNeighbor = queue.firstOrNull { it.node === neighbor.node } + if (existingNeighbor != null) { + if (neighbor.g < existingNeighbor.g) { + existingNeighbor.g = neighbor.g + existingNeighbor.parent = neighbor.parent + } + } else { + queue.add(neighbor) + } + } + } + + return null + } + + private fun getNeighbors(node: NodeContainer): List { + return node.node.getTransferableNodes().map { + NodeContainer( + node = it, + parent = node, + g = node.g + 1, + f = 1 + ) + } + } + + data class NodeContainer(val node: TransportNode, var parent: NodeContainer?, var g: Int, var f: Int) { + fun collectPath(): List { + val set = mutableSetOf() + var current: NodeContainer? = this + + set.add(this.node) + + while (current?.parent != null) { + current = current.parent!! + set.add(current.node) + } + + return set.toList() + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as NodeContainer + + if (node != other.node) return false + if (g != other.g) return false + return f == other.f + } + + override fun hashCode(): Int { + var result = node.hashCode() + result = 31 * result + g + result = 31 * result + f + return result + } + } + + fun getResistance(node: TransportNode): Int = when (node) { + is SpongeNode -> node.positions.size + is EndRodNode -> 2 + else -> 1 + } + + fun getHeuristic(node: TransportNode, destination: TransportNode): Int { + val b = getResistance(node) + + val originPos = toVec3i(((node as? SingleNode)?.position ?: (node as? MultiNode<*, *>)?.positions?.first())!!) + val destinationPos = toVec3i(((destination as? SingleNode)?.position ?: (destination as? MultiNode<*, *>)?.positions?.first())!!) + + return originPos.distance(destinationPos).roundToInt() + b + } + override fun finalizeNodes() { @Suppress("UNCHECKED_CAST") val chunk = (holder as? ChunkNetworkHolder)?.manager?.chunk ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index 1034cf2134..f06bb8db2a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -18,10 +18,8 @@ class ChunkRegion(val world: IonWorld) { val size get() = chunks.values.size fun tickChunkTransport() { - scope.launch { - for ((_, chunk) in chunks) { - chunk.multiblockManager.tick() - } + for ((_, chunk) in chunks) { + chunk.multiblockManager.tick() } } From a723f52afed6169d2b25d2bd8fea85af0558e780 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 17 Sep 2024 14:04:18 -0500 Subject: [PATCH 176/500] performance improvements --- .../features/transport/node/NodeUtils.kt | 1 + .../features/transport/node/TransportNode.kt | 4 +- .../node/manager/node/PowerNodeManager.kt | 50 +++++++++---------- .../transport/node/power/SolarPanelNode.kt | 11 ++-- .../features/transport/node/type/MultiNode.kt | 43 ++++++++-------- .../transport/node/type/SingleNode.kt | 6 +++ 6 files changed, 60 insertions(+), 55 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt index 40718180d4..2c9a8273f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt @@ -106,6 +106,7 @@ fun > separateNodePositions(node: T): List> { return separated } + enum class NetworkType { POWER { override fun get(chunk: IonChunk): NodeManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index c9cb2eb1bf..736b56cd93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManag import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer @@ -71,7 +72,7 @@ abstract class TransportNode : PDCSerializable = ArrayDeque(getTransferableNodes()) + var cachedTransferable: ArrayDeque = ArrayDeque(getTransferableNodes()) fun refreshTransferCache() { cachedTransferable = ArrayDeque(getTransferableNodes()) @@ -87,6 +88,7 @@ abstract class TransportNode : PDCSerializable) : NodeManager(ho solarPanels.forEach(::tickSolarPanel) } - fun tickExtractor(extractorNode: PowerExtractorNode) { + private fun tickExtractor(extractorNode: PowerExtractorNode) { val powerCheck = extractorNode.getTransferPower() if (powerCheck == 0) return val destinations: ObjectOpenHashSet @@ -86,21 +83,20 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho transferTime = measureNanoTime { runPowerTransfer(extractorNode, destinations.toList(), extractorNode.getTransferPower()) } } - - println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") + println("Extractor transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") } - fun tickSolarPanel(panelNode: SolarPanelNode) { - val powerCheck = panelNode.getPower() + private fun tickSolarPanel(solarPanelNode: SolarPanelNode) { + val powerCheck = solarPanelNode.getPower() if (powerCheck == 0) return val destinations: ObjectOpenHashSet val floodFillTime: Long val transferTime: Long val fullTransferTime = measureNanoTime { - floodFillTime = measureNanoTime { destinations = getNetworkDestinations(panelNode) } + floodFillTime = measureNanoTime { destinations = getNetworkDestinations(solarPanelNode) } - transferTime = measureNanoTime { runPowerTransfer(panelNode, destinations.toList(), panelNode.tickAndGetPower()) } + transferTime = measureNanoTime { runPowerTransfer(solarPanelNode, destinations.toList(), solarPanelNode.tickAndGetPower()) } } println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") @@ -138,7 +134,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho var maximumResistance: Double = -1.0 - val paths: Array?> = Array(numDestinations) { runCatching { getPath(source, destinations[it]) }.getOrNull() } + val paths: Array?> = Array(numDestinations) { runCatching { pathfind(source, destinations[it]) }.getOrNull() } // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { @@ -181,7 +177,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ - private fun getPath(from: TransportNode, to: TransportNode): List? { + private fun pathfind(from: TransportNode, to: TransportNode): List? { val queue = ArrayDeque(1) queue.add(NodeContainer(from, null, 0, getHeuristic(from, to))) @@ -194,7 +190,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho val current = queue.minBy { it.f } if (current.node == to) { - return current.collectPath() + return current.buildPath() } queue.remove(current) @@ -202,7 +198,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho for (neighbor in getNeighbors(current)) { if (visited.contains(neighbor)) continue - neighbor.f = neighbor.g + getHeuristic(neighbor.node, to) + neighbor.f = (neighbor.g + getHeuristic(neighbor.node, to)) val existingNeighbor = queue.firstOrNull { it.node === neighbor.node } if (existingNeighbor != null) { @@ -219,10 +215,11 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho return null } - private fun getNeighbors(node: NodeContainer): List { - return node.node.getTransferableNodes().map { + private fun getNeighbors(node: NodeContainer): Array { + val transferable = node.node.cachedTransferable + return Array(transferable.size) { NodeContainer( - node = it, + node = transferable[it], parent = node, g = node.g + 1, f = 1 @@ -231,18 +228,16 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } data class NodeContainer(val node: TransportNode, var parent: NodeContainer?, var g: Int, var f: Int) { - fun collectPath(): List { - val set = mutableSetOf() + fun buildPath(): List { + val list = mutableListOf(this.node) var current: NodeContainer? = this - set.add(this.node) - while (current?.parent != null) { current = current.parent!! - set.add(current.node) + list.add(current.node) } - return set.toList() + return list } override fun equals(other: Any?): Boolean { @@ -265,6 +260,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } fun getResistance(node: TransportNode): Int = when (node) { + //TODO better system is SpongeNode -> node.positions.size is EndRodNode -> 2 else -> 1 @@ -272,11 +268,11 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho fun getHeuristic(node: TransportNode, destination: TransportNode): Int { val b = getResistance(node) + return getDistance(node, destination) + b + } - val originPos = toVec3i(((node as? SingleNode)?.position ?: (node as? MultiNode<*, *>)?.positions?.first())!!) - val destinationPos = toVec3i(((destination as? SingleNode)?.position ?: (destination as? MultiNode<*, *>)?.positions?.first())!!) - - return originPos.distance(destinationPos).roundToInt() + b + fun getDistance(from: TransportNode, destination: TransportNode): Int { + return from.getCenter().distance(destination.getCenter()).toInt() } override fun finalizeNodes() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 4ca693424d..3b9da20268 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -195,6 +195,8 @@ class SolarPanelNode( buildRelations(position) } + storedCenter = calculateCenter() + return this } @@ -213,19 +215,14 @@ class SolarPanelNode( positions.remove(otherPos) manager.nodes.remove(otherPos) } + + storedCenter = calculateCenter() } override fun addBack(position: BlockKey) { manager.nodeFactory.addSolarPanel(position, handleRelationships = false) } - override fun rebuildNode(position: BlockKey) { - manager.solarPanels.remove(this) - detectorPositions.clear() - - super.rebuildNode(position) - } - override fun loadIntoNetwork() { super.loadIntoNetwork() manager.solarPanels += this diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index c2bf0543b0..0c4b44a7a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -4,9 +4,12 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.node.separateNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.averageBy import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import java.util.concurrent.ConcurrentHashMap @@ -17,24 +20,6 @@ abstract class MultiNode, Z: MultiNode> : Tran /** The positions occupied by the node **/ val positions: MutableSet = ConcurrentHashMap.newKeySet() - /** - * Rebuild the node during the removal process - * - * When a position in a multi node is removed, the removed position is removed - * from the list of contained positions, and the node is rebuilt using this method. - **/ - open fun rebuildNode(position: BlockKey) { - // Create new nodes, automatically merging together - positions.forEach { - addBack(it) - } - - // Handle relations once fully rebuilt - positions.forEach { - manager.nodes[it]?.buildRelations(it) - } - } - /** * Adds new a position to this node **/ @@ -44,6 +29,8 @@ abstract class MultiNode, Z: MultiNode> : Tran onPlace(position) + storedCenter = calculateCenter() + @Suppress("UNCHECKED_CAST") return this as Self } @@ -58,6 +45,8 @@ abstract class MultiNode, Z: MultiNode> : Tran onPlace(position) } + + storedCenter = calculateCenter() } /** @@ -106,12 +95,16 @@ abstract class MultiNode, Z: MultiNode> : Tran positions.clear() clearRelations() } + + storedCenter = calculateCenter() } override fun loadIntoNetwork() { for (key in positions) { manager.nodes[key] = this } + + storedCenter = calculateCenter() } /** @@ -150,7 +143,17 @@ abstract class MultiNode, Z: MultiNode> : Tran return positions.size < maxPositions } - fun removeFromNetwork() { - positions.forEach { manager.nodes.remove(it) } + var storedCenter: Vec3i = this.calculateCenter() + + fun calculateCenter(): Vec3i { + val xAvg = positions.averageBy { getX(it).toDouble() } + val yAvg = positions.averageBy { getY(it).toDouble() } + val zAvg = positions.averageBy { getZ(it).toDouble() } + + return Vec3i(xAvg.toInt(), yAvg.toInt(), zAvg.toInt()) + } + + override fun getCenter(): Vec3i { + return storedCenter } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index e8900935a6..07cfc946a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -3,7 +3,9 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import kotlin.properties.Delegates /** @@ -37,4 +39,8 @@ abstract class SingleNode : TransportNode() { manager.nodes.remove(position) clearRelations() } + + override fun getCenter(): Vec3i { + return toVec3i(position) + } } From 5cc744adf5548ac6b9d870d3db92b6d827c50c39 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 18 Sep 2024 02:04:25 -0500 Subject: [PATCH 177/500] async ticking --- .../features/multiblock/MultiblockAccess.kt | 4 +- .../server/features/transport/Extractors.kt | 2 +- .../server/features/transport/IonChangeSet.kt | 23 ++++++++- .../server/features/transport/NewTransport.kt | 22 +++++++-- .../node/manager/ChunkTransportManager.kt | 3 ++ .../manager/holders/ChunkNetworkHolder.kt | 2 + .../node/manager/node/NodeManager.kt | 2 + .../node/manager/node/PowerNodeManager.kt | 49 ++++++++++--------- .../transport/node/power/SolarPanelNode.kt | 7 ++- .../server/features/world/chunk/IonChunk.kt | 4 +- 10 files changed, 84 insertions(+), 34 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 426262b92c..8817a62975 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -152,7 +152,7 @@ object MultiblockAccess : IonServerComponent() { * * @return if the multiblock could be created properly. **/ - fun setMultiblock(detector: Player, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace, multiblock: Multiblock): Boolean { + fun setMultiblock(detector: Player?, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace, multiblock: Multiblock): Boolean { val signBlock = MultiblockEntity.getSignFromOrigin(world, Vec3i(x, y, z), structureDirection) val sign = signBlock.state as? Sign ?: return false @@ -165,7 +165,7 @@ object MultiblockAccess : IonServerComponent() { sign.isWaxed = true - multiblock.setupSign(detector, sign) + if (detector != null) multiblock.setupSign(detector, sign) sign.update(false, false) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt index f51b4c246e..a051ae5f05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt @@ -39,7 +39,7 @@ import kotlin.collections.set import kotlin.concurrent.fixedRateTimer object Extractors : IonServerComponent() { - private const val extractorTicksPerSecond = 1.0 + const val extractorTicksPerSecond = 1.0 val EXTRACTOR_BLOCK = Material.CRAFTING_TABLE diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt index b759d49ec6..855a0252fb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt @@ -7,7 +7,12 @@ import com.sk89q.worldedit.history.change.Change import com.sk89q.worldedit.world.World import com.sk89q.worldedit.world.biome.BiomeType import com.sk89q.worldedit.world.block.BlockTypesCache +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import org.bukkit.block.Sign import java.util.Collections class IonChangeSet(world: World) : AbstractChangeSet(world) { @@ -17,14 +22,30 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { override fun add(x: Int, y: Int, z: Int, combinedFrom: Int, combinedTo: Int) { counter++ addWriteTask { + val data = BukkitAdapter.adapt(BlockTypesCache.states[combinedTo]) + val type = BukkitAdapter.adapt(BlockTypesCache.states[combinedTo].blockType) + GlobalNodeManager.handleBlockChange( bukkitWorld, toBlockKey(x, y, z), - BukkitAdapter.adapt(BlockTypesCache.states[combinedTo]) + data ) + + if (type.isWallSign) { + val state = bukkitWorld.getBlockState(x, y, z) as? Sign + if (state != null) processMultiblock(state) + } } } + private fun processMultiblock(sign: Sign) { + val multiblockType = MultiblockAccess.getFast(sign) ?: return + val structureDirection = sign.getFacing().oppositeFace + + val origin = MultiblockEntity.getOriginFromSign(sign) + MultiblockAccess.setMultiblock(null, bukkitWorld, origin.x, origin.y, origin.z, structureDirection, multiblockType) + } + private var recording: Boolean = true override fun isRecordingChanges(): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index bbcb9085eb..67ab825d9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -3,20 +3,36 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.transport.node.manager.TransportManager import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import java.util.Timer import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ExecutorService import java.util.concurrent.Executors +import kotlin.concurrent.fixedRateTimer object NewTransport : IonServerComponent() { private val transportManagers = ConcurrentHashMap.newKeySet() - lateinit var thread: ExecutorService + + lateinit var monitorThread: Timer + lateinit var executor: ExecutorService override fun onEnable() { - thread = Executors.newFixedThreadPool(128, Tasks.namedThreadFactory("wire-transport")) + executor = Executors.newFixedThreadPool(64, Tasks.namedThreadFactory("wire-transport")) + + val interval: Long = (1000 / Extractors.extractorTicksPerSecond).toLong() + monitorThread = fixedRateTimer(name = "Extractor Tick", daemon = true, initialDelay = interval, period = interval) { + transportManagers.forEach { + try { + it.tick() + } catch (exception: Exception) { + exception.printStackTrace() + } + } + } } override fun onDisable() { - if (::thread.isInitialized) thread.shutdown() + if (::executor.isInitialized) executor.shutdown() + if (::monitorThread.isInitialized) executor.shutdown() } fun registerTransportManager(manager: TransportManager) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt index ab24882740..e627046d4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.manager +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager @@ -19,11 +20,13 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { fun setup() { powerNodeManager.handleLoad() fluidNodeManager.handleLoad() + NewTransport.registerTransportManager(this) } fun onUnload() { powerNodeManager.handleUnload() fluidNodeManager.handleUnload() + NewTransport.removeTransportManager(this) } fun save() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index afd0547acc..4d6022a240 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -84,6 +84,8 @@ class ChunkNetworkHolder private constructor (val manager: Chunk network.buildRelations() network.finalizeNodes() + + network.ready = true } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt index 78047f6c43..028ef82967 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt @@ -26,6 +26,8 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { abstract val nodeFactory: NodeFactory<*> abstract val dataVersion: Int + var ready: Boolean = false + open fun processBlockRemoval(key: BlockKey) { val previousNode = nodes[key] ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index 349a5ce587..ed0f0ae8df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.manager.node import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder @@ -70,36 +71,40 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } private fun tickExtractor(extractorNode: PowerExtractorNode) { - val powerCheck = extractorNode.getTransferPower() - if (powerCheck == 0) return - val destinations: ObjectOpenHashSet - - val floodFillTime: Long - val transferTime: Long - val fullTransferTime = measureNanoTime { - floodFillTime = measureNanoTime { destinations = getNetworkDestinations(extractorNode) } - - extractorNode.markTicked() - transferTime = measureNanoTime { runPowerTransfer(extractorNode, destinations.toList(), extractorNode.getTransferPower()) } + NewTransport.executor.submit { + val powerCheck = extractorNode.getTransferPower() + if (powerCheck == 0) return@submit + val destinations: ObjectOpenHashSet + + val floodFillTime: Long + val transferTime: Long + val fullTransferTime = measureNanoTime { + floodFillTime = measureNanoTime { destinations = getNetworkDestinations(extractorNode) } + + extractorNode.markTicked() + transferTime = measureNanoTime { runPowerTransfer(extractorNode, destinations.toList(), extractorNode.getTransferPower()) } + } } - println("Extractor transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") +// println("Extractor transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") } private fun tickSolarPanel(solarPanelNode: SolarPanelNode) { - val powerCheck = solarPanelNode.getPower() - if (powerCheck == 0) return - val destinations: ObjectOpenHashSet + NewTransport.executor.submit { + val powerCheck = solarPanelNode.getPower() + if (powerCheck == 0) return@submit + val destinations: ObjectOpenHashSet - val floodFillTime: Long - val transferTime: Long - val fullTransferTime = measureNanoTime { - floodFillTime = measureNanoTime { destinations = getNetworkDestinations(solarPanelNode) } + val floodFillTime: Long + val transferTime: Long + val fullTransferTime = measureNanoTime { + floodFillTime = measureNanoTime { destinations = getNetworkDestinations(solarPanelNode) } - transferTime = measureNanoTime { runPowerTransfer(solarPanelNode, destinations.toList(), solarPanelNode.tickAndGetPower()) } + transferTime = measureNanoTime { runPowerTransfer(solarPanelNode, destinations.toList(), solarPanelNode.tickAndGetPower()) } + } } - println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") +// println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") } private fun getNetworkDestinations(origin: TransportNode): ObjectOpenHashSet { @@ -128,7 +133,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho **/ fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int) { if (destinations.isEmpty()) return - println("Sending $availableTransferPower to ${destinations.size} destinations") +// println("Sending $availableTransferPower to ${destinations.size} destinations") val numDestinations = destinations.size diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 3b9da20268..892da7b26d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -13,7 +13,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded @@ -260,5 +259,9 @@ class SolarPanelNode( } } - override fun toString(): String = "(SOLAR PANEL NODE: Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, distance = $exitDistance, powerRatio = ${getPowerRatio()}, location = ${toVec3i(positions.random())}" + override fun toString(): String = "(SOLAR PANEL NODE:" + + " Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, " + + "distance = $exitDistance," + + " powerRatio = ${getPowerRatio()}, " + + "location = ${getCenter()}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index d2e5473f61..137c012e27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -82,9 +82,7 @@ class IonChunk( /** * Logic upon world tick **/ - fun tick() { - transportNetwork.tick() - } + fun tick() {} /** * Gets the neighboring chunk in this direction From 8ebc0ceeb328f207afeb4c641226ae46010c8c04 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 19 Sep 2024 14:05:35 -0500 Subject: [PATCH 178/500] better implementation of transfer, pathfinding resistance, code cleanup and generalization --- .../entity/type/power/PowerStorage.kt | 4 + .../transport/node/NodePathfinding.kt | 144 ++++++++++ .../features/transport/node/TransportNode.kt | 31 ++- .../transport/node/fluid/FluidInputNode.kt | 4 + .../transport/node/general/JunctionNode.kt | 36 +++ .../transport/node/general/LinearNode.kt | 4 + .../node/manager/TransportManager.kt | 2 +- .../node/manager/node/PowerNodeManager.kt | 262 +++++------------- .../node/power/InvertedDirectionalNode.kt | 4 + .../node/power/PowerDirectionalNode.kt | 4 + .../node/power/PowerEqualSplitterNode.kt | 4 + .../node/power/PowerExtractorNode.kt | 55 ++-- .../transport/node/power/PowerFlowMeter.kt | 5 + .../transport/node/power/PowerInputNode.kt | 4 + .../transport/node/power/SolarPanelNode.kt | 7 +- .../server/miscellaneous/utils/Collections.kt | 2 + 16 files changed, 353 insertions(+), 219 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index 0b6fab55d2..2b3659c8fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -76,6 +76,10 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit return getPower() - amount > 0 } + fun getRemainingCapacity(): Int { + return capacity - getPower() + } + private val updateHandlers = ConcurrentHashMap.newKeySet<(PowerStorage) -> Unit>() fun registerUpdateHandler(handler: (PowerStorage) -> Unit) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt new file mode 100644 index 0000000000..fad4dbbc47 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt @@ -0,0 +1,144 @@ +package net.horizonsend.ion.server.features.transport.node + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import kotlin.math.roundToInt + +inline fun getNetworkDestinations(origin: TransportNode, check: (T) -> Boolean): ObjectOpenHashSet { + val visitQueue = ArrayDeque() + val visitedSet = ObjectOpenHashSet() + val destinations = ObjectOpenHashSet() + + visitQueue.addAll(origin.cachedTransferable) + + while (visitQueue.isNotEmpty()) { + val currentNode = visitQueue.removeFirst() + visitedSet.add(currentNode) + + if (currentNode is T && check(currentNode)) { + destinations.add(currentNode) + } + + visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) + } + + return destinations +} + +/** + * Uses the A* algorithm to find the shortest available path between these two nodes. + **/ +fun getIdealPath(from: TransportNode, to: TransportNode): Array? { + val queue = ArrayDeque(1) + queue.add(PathfindingNodeWrapper(from, null, 0, 0)) + + val visited = ArrayDeque() + + var iterations = 0 + + while (queue.isNotEmpty() && iterations < 150) { + iterations++ + val current = queue.minBy { it.f } + + if (current.node == to) { + return current.buildPath() + } + + queue.remove(current) + visited.add(current) + + for (neighbor in getNeighbors(current)) { + if (visited.contains(neighbor)) continue + neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) + + val existingNeighbor = queue.firstOrNull { it.node === neighbor.node } + if (existingNeighbor != null) { + if (neighbor.g < existingNeighbor.g) { + existingNeighbor.g = neighbor.g + existingNeighbor.parent = neighbor.parent + } + } else { + queue.add(neighbor) + } + } + } + + return null +} + +// Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution +private fun getNeighbors(parent: PathfindingNodeWrapper): Array { + val transferable = parent.node.cachedTransferable + return Array(transferable.size) { + val neighbor = transferable[it] + + PathfindingNodeWrapper( + node = neighbor, + parent = parent, + g = parent.g + parent.node.getDistance(neighbor).roundToInt(), + f = 1 + ) + } +} + +// The heuristic used for the algorithm in this case is the distance from the node to the destination, which is typical, +// But it also includes the pathfinding resistance to try to find the least resistant path. +fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: TransportNode): Int { + val resistance = wrapper.node.getPathfindingResistance(wrapper.parent?.node, null) + return wrapper.node.getDistance(destination).roundToInt() + resistance +} + +data class PathfindingNodeWrapper(val node: TransportNode, var parent: PathfindingNodeWrapper?, var g: Int, var f: Int) { + // Compiles the path + fun buildPath(): Array { + val list = mutableListOf(this.node) + var current: PathfindingNodeWrapper? = this + + while (current?.parent != null) { + current = current.parent!! + list.add(current.node) + } + + // Return a reversed array, to put the origin node at the head of the array + val lastIndex = list.lastIndex + return Array(list.size) { + list[lastIndex - it] + } + } + + // + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as PathfindingNodeWrapper + + if (node != other.node) return false + if (g != other.g) return false + return f == other.f + } + + override fun hashCode(): Int { + var result = node.hashCode() + result = 31 * result + g + result = 31 * result + f + return result + } + // +} + +fun calculatePathResistance(path: Array?): Double? { + if (path == null) return null + + var sum = 0.0 + + for (index in path.indices) { + val current = path[index] + + sum += current.getPathfindingResistance( + previousNode = path.getOrNull(index - 1), + nextNode = path.getOrNull(index + 1) + ) + } + + return sum +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 736b56cd93..6722294c82 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -19,12 +19,11 @@ abstract class TransportNode : PDCSerializable = ConcurrentHashMap() - abstract val type: NodeType - /** * Break all relations between this node and others **/ @@ -72,6 +71,9 @@ abstract class TransportNode : PDCSerializable = ArrayDeque(getTransferableNodes()) fun refreshTransferCache() { @@ -88,8 +90,6 @@ abstract class TransportNode : PDCSerializable { + return relationships.filter { it.value.other == other } + } + + /** + * Get the center of this node, for display and pathfinding. + **/ + abstract fun getCenter(): Vec3i + + /** + * Get the distance between the nodes by using their relative center. + **/ + fun getDistance(previous: TransportNode): Double { + return previous.getCenter().distance(getCenter()) + } + + // companion object : PersistentDataType { override fun getPrimitiveType() = PersistentDataContainer::class.java override fun getComplexType() = TransportNode::class.java @@ -164,4 +186,5 @@ abstract class TransportNode : PDCSerializable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt index 931a1205e9..9076f47147 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt @@ -34,4 +34,8 @@ class FluidInputNode(override val manager: FluidNodeManager) : SingleNode() { } var boundMultiblockEntity: FluidStoringEntity? = null + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 0 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt index 59412e03db..174c420b8d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt @@ -6,8 +6,14 @@ import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNo import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.averageBy +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import kotlin.math.roundToInt abstract class JunctionNode, B: JunctionNode>(override val manager: T) : MultiNode() { override fun isTransferableTo(node: TransportNode): Boolean { @@ -22,4 +28,34 @@ abstract class JunctionNode, B: Junctio override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + if (previousNode != null) { + if (nextNode != null) { + // Provided both means it needs to be more precise for an accurate distribution of resources. Get in / out locations via relations + val relationPrevious = getRelationshipWith(previousNode) + val relationNext = getRelationshipWith(previousNode) + + val previousVec = Vec3i( + relationPrevious.keys.averageBy { getX(it).toDouble() }.roundToInt(), + relationPrevious.keys.averageBy { getY(it).toDouble() }.roundToInt(), + relationPrevious.keys.averageBy { getZ(it).toDouble() }.roundToInt() + ) + + val nextVec = Vec3i( + relationNext.keys.averageBy { getX(it).toDouble() }.roundToInt(), + relationNext.keys.averageBy { getY(it).toDouble() }.roundToInt(), + relationNext.keys.averageBy { getZ(it).toDouble() }.roundToInt() + ) + + return previousVec.distance(nextVec).roundToInt() + } + + // Rough distance + return getCenter().distance(previousNode.getCenter()).roundToInt() + } + + // As a fallback, shouldn't happen + return 0 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt index ed0ffe7c99..ced147407f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt @@ -45,5 +45,9 @@ abstract class LinearNode, B: LinearNode< persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), axis) } + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return positions.size // Always in one end and out the other + } + override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationships.size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt index ce4485fea4..3ed5b1bc7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -9,6 +9,6 @@ abstract class TransportManager { abstract val fluidNodeManager: NetworkHolder fun tick() { - powerNodeManager.network.tick() + powerNodeManager.network.tickTransport() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt index ed0f0ae8df..96d5773b61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt @@ -5,15 +5,16 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.calculatePathResistance +import net.horizonsend.ion.server.features.transport.node.getIdealPath +import net.horizonsend.ion.server.features.transport.node.getNetworkDestinations import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.node.power.SpongeNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -21,7 +22,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap import kotlin.math.roundToInt -import kotlin.system.measureNanoTime class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER @@ -41,105 +41,43 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho extractors.clear() } - /** - * Handle the addition of a new powered multiblock entity - **/ - fun tryBindPowerNode(new: PoweredMultiblockEntity) { - // All directions - val inputVec = new.getRealInputLocation() - val inputKey = toBlockKey(inputVec) - - val inputNode = getNode(inputKey) as? PowerInputNode - - if (inputNode != null) { - new.bindInputNode(inputNode) - return - } - - val (x, y, z) = inputVec - val block = getBlockIfLoaded(world, x, y, z) - if (block != null) createNodeFromBlock(block) - - val attemptTwo = getNode(inputKey) as? PowerInputNode ?: return - - new.bindInputNode(attemptTwo) - } - - fun tick() { + fun tickTransport() { extractors.values.forEach(::tickExtractor) solarPanels.forEach(::tickSolarPanel) } - private fun tickExtractor(extractorNode: PowerExtractorNode) { - NewTransport.executor.submit { - val powerCheck = extractorNode.getTransferPower() - if (powerCheck == 0) return@submit - val destinations: ObjectOpenHashSet - - val floodFillTime: Long - val transferTime: Long - val fullTransferTime = measureNanoTime { - floodFillTime = measureNanoTime { destinations = getNetworkDestinations(extractorNode) } - - extractorNode.markTicked() - transferTime = measureNanoTime { runPowerTransfer(extractorNode, destinations.toList(), extractorNode.getTransferPower()) } - } - } + private fun tickExtractor(extractorNode: PowerExtractorNode) = NewTransport.executor.submit { + val powerCheck = extractorNode.getTransferPower() + if (powerCheck == 0) return@submit -// println("Extractor transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") + val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) + val transferred = extractorNode.getTransferPower() + runPowerTransfer(extractorNode, destinations.toList(), transferred) + extractorNode.markTicked() } - private fun tickSolarPanel(solarPanelNode: SolarPanelNode) { - NewTransport.executor.submit { - val powerCheck = solarPanelNode.getPower() - if (powerCheck == 0) return@submit - val destinations: ObjectOpenHashSet + private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { + val powerCheck = solarPanelNode.getPower() + if (powerCheck == 0) return@submit - val floodFillTime: Long - val transferTime: Long - val fullTransferTime = measureNanoTime { - floodFillTime = measureNanoTime { destinations = getNetworkDestinations(solarPanelNode) } - - transferTime = measureNanoTime { runPowerTransfer(solarPanelNode, destinations.toList(), solarPanelNode.tickAndGetPower()) } - } - } - -// println("Solar panel transfer took $fullTransferTime, flood fill took $floodFillTime, pathfind & transfer calcs took $transferTime") + val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) + runPowerTransfer(solarPanelNode, destinations.toList(), solarPanelNode.tickAndGetPower()) } - private fun getNetworkDestinations(origin: TransportNode): ObjectOpenHashSet { - val visitQueue = ArrayDeque() - val visitedSet = ObjectOpenHashSet() - val destinations = ObjectOpenHashSet() - - visitQueue.addAll(origin.getTransferableNodes()) - - while (visitQueue.isNotEmpty()) { - val currentNode = visitQueue.removeFirst() - visitedSet.add(currentNode) - - if (currentNode is PowerInputNode && currentNode.isCalling()) { - destinations.add(currentNode) - } - - visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) - } - - return destinations - } + private fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } /** - * Runs the power transfer fr + * Runs the power transfer from the source to the destinations. pending rewrite **/ - fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int) { - if (destinations.isEmpty()) return -// println("Sending $availableTransferPower to ${destinations.size} destinations") - + private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { + if (destinations.isEmpty()) return availableTransferPower val numDestinations = destinations.size var maximumResistance: Double = -1.0 - val paths: Array?> = Array(numDestinations) { runCatching { pathfind(source, destinations[it]) }.getOrNull() } + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(source, destinations[it]) + }.getOrNull() } // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { @@ -150,139 +88,87 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } // All null, no paths found - if (maximumResistance == -1.0) return + if (maximumResistance == -1.0) return availableTransferPower - var shareSum = 0.0 + var shareFactorSum = 0.0 val shareFactors: Array = Array(numDestinations) { index -> val resistance = pathResistance[index] ?: return@Array null val fac = (numDestinations - index).toDouble() / (resistance / maximumResistance) - shareSum += fac + shareFactorSum += fac fac } - for ((index, destination) in destinations.withIndex()) { - val shareFactor = shareFactors[index] ?: return - val share = shareFactor / shareSum + var remainingPower = availableTransferPower - val sent = availableTransferPower * share // TODO more complex transfer code + // Just cast once + val powerSource = source as? PowerExtractorNode - paths[index]?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(sent.roundToInt()) } - destination.boundMultiblockEntity?.storage?.addPower(sent.toInt()) - } - } + for ((index, destination) in destinations.withIndex()) { + val shareFactor = shareFactors[index] ?: continue + val share = shareFactor / shareFactorSum - fun calculatePathResistance(path: List?): Double? { - if (path == null) return null + val recipient = destination.boundMultiblockEntity - return 1.0 - } + if (recipient == null) { + // Remove this share factor from the sum, since it is not taking up any power + shareFactorSum -= shareFactor + continue + } - /** - * Uses the A* algorithm to find the shortest available path between these two nodes. - **/ - private fun pathfind(from: TransportNode, to: TransportNode): List? { - val queue = ArrayDeque(1) - queue.add(NodeContainer(from, null, 0, getHeuristic(from, to))) + val idealSend = (availableTransferPower * share).roundToInt() + val toSend = minOf(idealSend, recipient.storage.getRemainingCapacity()) + val couldNotRemove = powerSource?.drawPower(toSend) ?: 0 // If null, source is a solar panel, and can't be removed from. - val visited = mutableListOf() + val realAdd = toSend - couldNotRemove - var iterations = 0 + val remainder = recipient.storage.addPower(realAdd) + val realTaken = realAdd - remainder - while (queue.isNotEmpty() && iterations < 150) { - iterations++ - val current = queue.minBy { it.f } + remainingPower -= realTaken + paths[index]?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(realTaken) } - if (current.node == to) { - return current.buildPath() - } + // All sent + if (remainder == 0) continue - queue.remove(current) - visited.add(current) - - for (neighbor in getNeighbors(current)) { - if (visited.contains(neighbor)) continue - neighbor.f = (neighbor.g + getHeuristic(neighbor.node, to)) - - val existingNeighbor = queue.firstOrNull { it.node === neighbor.node } - if (existingNeighbor != null) { - if (neighbor.g < existingNeighbor.g) { - existingNeighbor.g = neighbor.g - existingNeighbor.parent = neighbor.parent - } - } else { - queue.add(neighbor) - } - } + // Get the proportion of the amount of power that sent compared to the ideal calculations. + val usedShare = realTaken.toDouble() / idealSend.toDouble() + // Use that to get a proportion of the share factor, and remove that from the sum. + val toRemove = shareFactor * usedShare + shareFactorSum -= toRemove } - return null + return remainingPower } - private fun getNeighbors(node: NodeContainer): Array { - val transferable = node.node.cachedTransferable - return Array(transferable.size) { - NodeContainer( - node = transferable[it], - parent = node, - g = node.g + 1, - f = 1 - ) - } + override fun finalizeNodes() { + @Suppress("UNCHECKED_CAST") + val chunk = (holder as? ChunkNetworkHolder)?.manager?.chunk ?: return + chunk.multiblockManager.getAllMultiblockEntities().values.filterIsInstance().forEach(::tryBindPowerNode) } - data class NodeContainer(val node: TransportNode, var parent: NodeContainer?, var g: Int, var f: Int) { - fun buildPath(): List { - val list = mutableListOf(this.node) - var current: NodeContainer? = this - - while (current?.parent != null) { - current = current.parent!! - list.add(current.node) - } - - return list - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as NodeContainer + /** + * Handle the addition of a new powered multiblock entity + **/ + fun tryBindPowerNode(new: PoweredMultiblockEntity) { + // All directions + val inputVec = new.getRealInputLocation() + val inputKey = toBlockKey(inputVec) - if (node != other.node) return false - if (g != other.g) return false - return f == other.f - } + val inputNode = getNode(inputKey) as? PowerInputNode - override fun hashCode(): Int { - var result = node.hashCode() - result = 31 * result + g - result = 31 * result + f - return result + if (inputNode != null) { + new.bindInputNode(inputNode) + return } - } - - fun getResistance(node: TransportNode): Int = when (node) { - //TODO better system - is SpongeNode -> node.positions.size - is EndRodNode -> 2 - else -> 1 - } - fun getHeuristic(node: TransportNode, destination: TransportNode): Int { - val b = getResistance(node) - return getDistance(node, destination) + b - } + val (x, y, z) = inputVec + val block = getBlockIfLoaded(world, x, y, z) + if (block != null) createNodeFromBlock(block) - fun getDistance(from: TransportNode, destination: TransportNode): Int { - return from.getCenter().distance(destination.getCenter()).toInt() - } + val attemptTwo = getNode(inputKey) as? PowerInputNode ?: return - override fun finalizeNodes() { - @Suppress("UNCHECKED_CAST") - val chunk = (holder as? ChunkNetworkHolder)?.manager?.chunk ?: return - chunk.multiblockManager.getAllMultiblockEntities().values.filterIsInstance().forEach(::tryBindPowerNode) + new.bindInputNode(attemptTwo) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt index 9fa0382368..bdcc582d4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt @@ -28,4 +28,8 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt index f76e34cf53..01d3da924f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt @@ -39,4 +39,8 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( companion object { val materialDataType = EnumDataType(Material::class.java) } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt index 153316c8e4..8e3e34f3ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt @@ -26,4 +26,8 @@ class PowerEqualSplitterNode(override val manager: PowerNodeManager) : SingleNod override fun loadData(persistentDataContainer: PersistentDataContainer) { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt index cc849ad8e3..9bc92d7a46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt @@ -6,9 +6,7 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt @@ -21,9 +19,6 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() network.extractors[position] = this } - val extractableNodes: MutableSet get() = relationships.mapNotNullTo(mutableSetOf()) { it.value.other as? PowerInputNode } - - // Region transfer /* * The extractor node should be allowed to transfer into any regular node. * @@ -47,9 +42,7 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() } - // End region - // Start region loading override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) } @@ -63,36 +56,48 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() manager.extractors[position] = this } + override fun onPlace(position: BlockKey) { + super.onPlace(position) + manager.extractors[position] = this + } + override fun handlePositionRemoval(position: BlockKey) { manager.extractors.remove(position) super.handlePositionRemoval(position) } - override fun buildRelations(position: BlockKey) { - for (offset in ADJACENT_BLOCK_FACES) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = manager.getNode(offsetKey) ?: continue + /** + * Attempts to draw power from connected inputs. + * Returns the amount that couldn't be removed. + **/ + fun drawPower(amount: Int): Int { + val entities = relationships.mapNotNull { (it.value.other as? PowerInputNode)?.boundMultiblockEntity } - if (this == neighborNode) return + var remaining = amount - if (neighborNode is PowerInputNode) { - extractableNodes.add(neighborNode) - } + while (remaining > 0) { + val available = entities.filterNot { it.storage.isEmpty() } + if (available.isEmpty()) break - // Add a relationship, if one should be added - addRelationship(position, neighborNode, offset) + val minPower = entities.minOf { it.storage.getPower() } + val idealShare = remaining / available.size + val toRemove = minOf(idealShare, minPower) + + available.forEach { + val r = it.storage.removePower(toRemove) + remaining -= (toRemove - r) + } } + + return remaining + } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 0 } override fun toString(): String { -// val destinations: Set -// val time = measureNanoTime { -// destinations = manager.tickExtractor(this) -// } -// -// debugAudience.highlightBlocks(destinations.map { toVec3i(it.position) }, 50L) - - return "Extractor. found"// ${destinations.size} in $time ns" + return "Extractor. found, can trasnsfer: ${getTransferPower()}" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt index 3d9abdd582..a4bc7e9132 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt @@ -47,6 +47,7 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { fun onCompleteChain(transferred: Int) { addTransferred(TransferredPower(transferred, System.currentTimeMillis())) + if (::displayHandler.isInitialized) displayHandler.update() } companion object { @@ -129,4 +130,8 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { } private data class TransferredPower(val transferred: Int, val time: Long) + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt index bfd95cd733..b2eba387c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt @@ -44,5 +44,9 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { // } // } + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 0 + } + override fun toString(): String = "POWER INPUT NODE. Bound to $boundMultiblockEntity" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt index 892da7b26d..4d4db86786 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt @@ -61,7 +61,7 @@ class SolarPanelNode( * This method is run upon neighbor unloads **/ private fun calculateExitDistance() { - val neighbors = getTransferableNodes() + val neighbors = cachedTransferable // Transferable node provides an exit if (neighbors.any { it !is SolarPanelNode }) { @@ -244,6 +244,11 @@ class SolarPanelNode( detectors?.let { detectorPositions.addAll(it.asIterable()) } } + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + // Further encourage the way out + return 1000 - exitDistance + } + companion object { const val POWER_PER_SECOND = 5 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index b32d47653d..a2b3da242c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -130,6 +130,8 @@ inline fun Map.filterKeysIsInstance(): Map { } inline fun Collection.averageBy(transform: (T) -> Double): Double { + if (size == 1) { return transform(first()) } + var total = 0.0 for (entry in this) { From e71e1913830731116d2a2ad8c1a5768600d81e40 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 19 Sep 2024 14:16:25 -0500 Subject: [PATCH 179/500] organize files --- .../server/command/admin/IonChunkCommand.kt | 4 +-- .../command/misc/TransportDebugCommand.kt | 6 ++-- .../command/qol/FixExtractorsCommand.kt | 2 +- .../modular/display/PowerFlowMeterDisplay.kt | 2 +- .../entity/type/fluids/FluidStoringEntity.kt | 7 ++--- .../type/power/PoweredMultiblockEntity.kt | 2 +- .../manager/ChunkMultiblockManager.kt | 4 +-- .../multiblock/manager/MultiblockManager.kt | 6 ++-- .../manager/ShipMultiblockManager.kt | 4 +-- .../multiblock/shape/MultiblockShape.kt | 6 ++-- .../defense/passive/areashield/AreaShield.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 2 +- .../type/power/charger/ChargerMultiblock.kt | 2 +- .../type/power/storage/PowerBankMultiblock.kt | 2 +- .../type/power/storage/PowerCellMultiblock.kt | 2 +- .../features/starship/PilotedStarships.kt | 2 +- .../factory/StarshipFactoryPrinter.kt | 2 +- .../features/transport/ExtractorData.kt | 31 ------------------- .../server/features/transport/NewTransport.kt | 1 + .../features/transport/node/NodeType.kt | 28 ++++++++--------- .../features/transport/node/TransportNode.kt | 2 +- .../node/fluid/FluidExtractorNode.kt | 4 --- .../node/fluid/GasDirectionalNode.kt | 4 --- .../transport/node/fluid/GasFilterNode.kt | 4 --- .../transport/node/fluid/GasFlowMeter.kt | 4 --- .../node/fluid/GasInvertedDirectionalNode.kt | 4 --- .../transport/node/fluid/GasValveNode.kt | 4 --- .../node/manager/ChunkTransportManager.kt | 2 -- .../manager/{node => }/FluidNodeManager.kt | 9 +++--- .../node/manager/{node => }/NodeManager.kt | 6 ++-- .../manager/{node => }/PowerNodeManager.kt | 20 ++++++------ .../node/manager/ShipTransportManager.kt | 2 -- .../node/manager/TransportManager.kt | 2 -- .../manager/holders/ChunkNetworkHolder.kt | 2 +- .../node/manager/holders/NetworkHolder.kt | 2 +- .../node/manager/holders/ShipNetworkHolder.kt | 2 +- .../features/transport/node/type/MultiNode.kt | 2 +- .../node/type/fluid/FluidExtractorNode.kt | 4 +++ .../node/{ => type}/fluid/FluidInputNode.kt | 4 +-- .../{ => type}/fluid/FluidJunctionNode.kt | 6 ++-- .../node/{ => type}/fluid/FluidNodeFactory.kt | 14 ++++----- .../node/type/fluid/GasDirectionalNode.kt | 4 +++ .../node/type/fluid/GasFilterNode.kt | 4 +++ .../transport/node/type/fluid/GasFlowMeter.kt | 4 +++ .../type/fluid/GasInvertedDirectionalNode.kt | 4 +++ .../transport/node/type/fluid/GasValveNode.kt | 4 +++ .../node/{ => type}/fluid/LightningRodNode.kt | 6 ++-- .../node/{ => type}/general/JunctionNode.kt | 8 ++--- .../node/{ => type}/general/LinearNode.kt | 8 ++--- .../node/{ => type}/power/EndRodNode.kt | 6 ++-- .../power/InvertedDirectionalNode.kt | 4 +-- .../{ => type}/power/PowerDirectionalNode.kt | 4 +-- .../power/PowerEqualSplitterNode.kt | 4 +-- .../{ => type}/power/PowerExtractorNode.kt | 4 +-- .../node/{ => type}/power/PowerFlowMeter.kt | 4 +-- .../node/{ => type}/power/PowerInputNode.kt | 4 +-- .../node/{ => type}/power/PowerNodeFactory.kt | 12 +++---- .../node/{ => type}/power/SolarPanelNode.kt | 6 ++-- .../node/{ => type}/power/SpongeNode.kt | 6 ++-- .../transport/node/{ => util}/NodeFactory.kt | 4 +-- .../node/{ => util}/NodePathfinding.kt | 3 +- .../transport/node/{ => util}/NodeUtils.kt | 5 +-- .../transport/{ => old}/Extractors.kt | 8 ++--- .../{ => old}/IonMetricsCollection.kt | 2 +- .../transport/{ => old}/TransportConfig.kt | 2 +- .../features/transport/{ => old}/Wires.kt | 4 +-- .../transport/{ => old}/pipe/PipeChainData.kt | 4 +-- .../transport/{ => old}/pipe/Pipes.kt | 12 +++---- .../{ => old}/pipe/filter/FilterData.kt | 2 +- .../{ => old}/pipe/filter/FilterDataKey.kt | 2 +- .../{ => old}/pipe/filter/FilterItemData.kt | 2 +- .../{ => old}/pipe/filter/Filters.kt | 6 ++-- .../miscellaneous/registrations/Components.kt | 10 +++--- 73 files changed, 172 insertions(+), 210 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/{node => }/FluidNodeManager.kt (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/{node => }/NodeManager.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/{node => }/PowerNodeManager.kt (88%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/fluid/FluidInputNode.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/fluid/FluidJunctionNode.kt (82%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/fluid/FluidNodeFactory.kt (86%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/fluid/LightningRodNode.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/general/JunctionNode.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/general/LinearNode.kt (90%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/EndRodNode.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/InvertedDirectionalNode.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/PowerDirectionalNode.kt (95%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/PowerEqualSplitterNode.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/PowerExtractorNode.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/PowerFlowMeter.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/PowerInputNode.kt (95%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/PowerNodeFactory.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/SolarPanelNode.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => type}/power/SpongeNode.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => util}/NodeFactory.kt (83%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => util}/NodePathfinding.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/{ => util}/NodeUtils.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/Extractors.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/IonMetricsCollection.kt (83%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/TransportConfig.kt (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/Wires.kt (99%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/pipe/PipeChainData.kt (72%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/pipe/Pipes.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/pipe/filter/FilterData.kt (72%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/pipe/filter/FilterDataKey.kt (68%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/pipe/filter/FilterItemData.kt (88%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => old}/pipe/filter/Filters.kt (95%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 0e44e9375a..471c5783c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -12,8 +12,8 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 2252d33b3c..30c37fae90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -5,9 +5,9 @@ import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand -import net.horizonsend.ion.server.features.transport.Extractors -import net.horizonsend.ion.server.features.transport.TransportConfig -import net.horizonsend.ion.server.features.transport.Wires +import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.old.TransportConfig +import net.horizonsend.ion.server.features.transport.old.Wires import org.bukkit.command.CommandSender import java.util.concurrent.Executors diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt index 6a78bf6e40..a22d77f6ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt @@ -6,7 +6,7 @@ import co.aikar.commands.annotation.Default import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand -import net.horizonsend.ion.server.features.transport.Extractors +import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt index a4aee5c4de..15911d65d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.client.display.modular.display -import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter import net.kyori.adventure.text.Component class PowerFlowMeterDisplay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 9f79c6bdbb..f21e090f71 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -115,7 +114,7 @@ interface FluidStoringEntity { ) } - fun getFluidInputNode(): FluidInputNode? { + fun getFluidInputNode(): net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode? { this as MultiblockEntity val block = getFluidInputLocation() @@ -123,11 +122,11 @@ interface FluidStoringEntity { val manager = chunk.transportNetwork.powerNodeManager val node = manager.getInternalNode(toBlockKey(block)) - if (node != null) return node as? FluidInputNode + if (node != null) return node as? net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode // Try to place unregistered node manager.manager.processBlockChange(world.getBlockAt(block.x, block.y, block.z)) - return manager.getInternalNode(toBlockKey(block)) as? FluidInputNode + return manager.getInternalNode(toBlockKey(block)) as? net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode } fun bindFluidInput() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index de15f6d007..9bdf395532 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 2543660897..014325d9ee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -4,8 +4,8 @@ import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index eff0c697b1..a9ec12936e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -9,9 +9,9 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index e1f5ca357f..43bf64bbad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -6,8 +6,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 970fcc032d..83d03a8a46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -8,9 +8,9 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_RE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync -import net.horizonsend.ion.server.features.transport.Extractors -import net.horizonsend.ion.server.features.transport.Wires -import net.horizonsend.ion.server.features.transport.pipe.Pipes +import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.old.Wires +import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.CONCRETE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.MATERIALS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 1cd15477b3..7daa1a94e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 711a8ced9f..c46cc5307b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -26,7 +26,7 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 477bc7ee19..032288e747 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -17,7 +17,7 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 26ecd134b2..b41c757aa0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 6684a1a0a9..9f29cf7e40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt index 6a7bd53627..cfb5200a66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt @@ -40,7 +40,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.misc.MiningLaserSu import net.horizonsend.ion.server.features.starship.subsystem.reactor.ReactorSubsystem import net.horizonsend.ion.server.features.starship.subsystem.shield.ShieldSubsystem import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields -import net.horizonsend.ion.server.features.transport.Extractors +import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.actualType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt index ea778f2eff..ae1bddf3b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.starship.factory import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.features.transport.Extractors +import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt deleted file mode 100644 index daaec4defd..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/ExtractorData.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.horizonsend.ion.server.features.transport - -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataType -import java.util.concurrent.ConcurrentLinkedQueue - -class ExtractorData( - val extractorLocations: ConcurrentLinkedQueue -) { - companion object : PersistentDataType { - override fun getPrimitiveType(): Class = LongArray::class.java - override fun getComplexType(): Class = ExtractorData::class.java - - override fun fromPrimitive(primitive: LongArray, context: PersistentDataAdapterContext): ExtractorData { - val list = ConcurrentLinkedQueue() - - for (key in primitive) { - list.add(toVec3i(key)) - } - - return ExtractorData(list) - } - - override fun toPrimitive(complex: ExtractorData, context: PersistentDataAdapterContext): LongArray { - return complex.extractorLocations.map { toBlockKey(it) }.toLongArray() - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 67ab825d9c..ce0f6d51f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.transport.node.manager.TransportManager +import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.miscellaneous.utils.Tasks import java.util.Timer import java.util.concurrent.ConcurrentHashMap diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index bd66b5a926..77d2b5f708 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -1,19 +1,17 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.node.fluid.FluidInputNode -import net.horizonsend.ion.server.features.transport.node.fluid.FluidJunctionNode -import net.horizonsend.ion.server.features.transport.node.fluid.LightningRodNode -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager -import net.horizonsend.ion.server.features.transport.node.power.EndRodNode -import net.horizonsend.ion.server.features.transport.node.power.InvertedDirectionalNode -import net.horizonsend.ion.server.features.transport.node.power.PowerDirectionalNode -import net.horizonsend.ion.server.features.transport.node.power.PowerEqualSplitterNode -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.type.fluid.LightningRodNode +import net.horizonsend.ion.server.features.transport.node.type.power.EndRodNode +import net.horizonsend.ion.server.features.transport.node.type.power.InvertedDirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerEqualSplitterNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.type.power.SpongeNode enum class NodeType(val clazz: Class) { //POWER @@ -28,8 +26,8 @@ enum class NodeType(val clazz: Class) { POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), //FLUID - FLUID_INPUT(FluidInputNode::class.java), - FLUID_JUNCTION(FluidJunctionNode::class.java), + FLUID_INPUT(net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode::class.java), + FLUID_JUNCTION(net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode::class.java), LIGHTNING_ROD(LightningRodNode::class.java), //ITEM diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 6722294c82..fc94a640d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.node import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidExtractorNode.kt deleted file mode 100644 index cf3612e6b7..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidExtractorNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.fluid - -class FluidExtractorNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt deleted file mode 100644 index 37458501be..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasDirectionalNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.fluid - -class GasDirectionalNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt deleted file mode 100644 index 64b7ff890e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFilterNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.fluid - -class GasFilterNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt deleted file mode 100644 index 61cae7a031..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasFlowMeter.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.fluid - -class GasFlowMeter { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt deleted file mode 100644 index 87bfc5611e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasInvertedDirectionalNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.fluid - -class GasInvertedDirectionalNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt deleted file mode 100644 index 3166c46cea..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/GasValveNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.fluid - -class GasValveNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt index e627046d4d..778fb26070 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt @@ -2,8 +2,6 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/FluidNodeManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index f681d60db9..a245daccfb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -1,9 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.manager.node +package net.horizonsend.ion.server.features.transport.node.manager -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.fluid.FluidExtractorNode -import net.horizonsend.ion.server.features.transport.node.fluid.FluidNodeFactory import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidNodeFactory +import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.GAS_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey @@ -14,7 +13,7 @@ class FluidNodeManager(holder: NetworkHolder) : NodeManager(ho override val type: NetworkType = NetworkType.FLUID override val nodeFactory = FluidNodeFactory(this) - val extractors: ConcurrentHashMap = ConcurrentHashMap() + val extractors: ConcurrentHashMap = ConcurrentHashMap() override val dataVersion: Int = 0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 028ef82967..f0f40cd674 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.transport.node.manager.node +package net.horizonsend.ion.server.features.transport.node.manager import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.features.transport.node.NetworkType -import net.horizonsend.ion.server.features.transport.node.NodeFactory import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.node.util.NodeFactory import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt similarity index 88% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 96d5773b61..9ff6320b94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/node/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -1,20 +1,20 @@ -package net.horizonsend.ion.server.features.transport.node.manager.node +package net.horizonsend.ion.server.features.transport.node.manager import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.node.NetworkType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.calculatePathResistance -import net.horizonsend.ion.server.features.transport.node.getIdealPath -import net.horizonsend.ion.server.features.transport.node.getNetworkDestinations import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.power.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.node.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.power.PowerNodeFactory -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerNodeFactory +import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.node.util.getIdealPath +import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index 49012601a1..fc5c2b1b3c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -3,8 +3,6 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.node.manager.holders.ShipNetworkHolder -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager class ShipTransportManager(val starship: Starship) : TransportManager() { override val powerNodeManager = ShipNetworkHolder(this) { PowerNodeManager(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt index 3ed5b1bc7e..828bff3fc5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager abstract class TransportManager { abstract val powerNodeManager: NetworkHolder diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 4d6022a240..5c5de2e4d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 4fb2dd15ba..6d55d9ac3e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index aa2758fb05..416e58286e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 0c4b44a7a2..12f3541721 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder -import net.horizonsend.ion.server.features.transport.node.separateNode +import net.horizonsend.ion.server.features.transport.node.util.separateNode import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.averageBy import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt new file mode 100644 index 0000000000..c900f1740d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.fluid + +class FluidExtractorNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt index 9076f47147..b4031978b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.node.fluid +package net.horizonsend.ion.server.features.transport.node.type.fluid import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt similarity index 82% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt index cdb63fed04..59734e4274 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.fluid +package net.horizonsend.ion.server.features.transport.node.type.fluid import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.general.JunctionNode -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey class FluidJunctionNode(network: FluidNodeManager) : JunctionNode(network) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt index 2b5df9ec7a..bfa8f73ccb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.transport.node.fluid +package net.horizonsend.ion.server.features.transport.node.type.fluid import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.transport.node.NodeFactory -import net.horizonsend.ion.server.features.transport.node.getNeighborNodes -import net.horizonsend.ion.server.features.transport.node.handleMerges -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.power.SpongeNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.power.SpongeNode +import net.horizonsend.ion.server.features.transport.node.util.NodeFactory +import net.horizonsend.ion.server.features.transport.node.util.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.util.handleMerges import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.faces @@ -88,7 +88,7 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory FluidJunctionNode(network, position).apply { loadIntoNetwork() } + 0 -> net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode(network, position).apply { loadIntoNetwork() } // Consolidate into neighbor 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt new file mode 100644 index 0000000000..e10a607f71 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.fluid + +class GasDirectionalNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt new file mode 100644 index 0000000000..a5b9cbd1a4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.fluid + +class GasFilterNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt new file mode 100644 index 0000000000..01de9350d1 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.fluid + +class GasFlowMeter { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt new file mode 100644 index 0000000000..087b772503 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.fluid + +class GasInvertedDirectionalNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt new file mode 100644 index 0000000000..3b5ee9832e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.fluid + +class GasValveNode { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/LightningRodNode.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/LightningRodNode.kt index 758ac18968..bbccd5b01a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/fluid/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/LightningRodNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.fluid +package net.horizonsend.ion.server.features.transport.node.type.fluid import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.general.LinearNode -import net.horizonsend.ion.server.features.transport.node.manager.node.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt index 174c420b8d..bb57d6d5a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.transport.node.general +package net.horizonsend.ion.server.features.transport.node.type.general import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.averageBy import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index ced147407f..2e854248eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.transport.node.general +package net.horizonsend.ion.server.features.transport.node.type.general import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager -import net.horizonsend.ion.server.features.transport.node.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt index 60c9667ec0..e7de30f217 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.general.LinearNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt index bdcc582d4d..148ce927fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index 01d3da924f..7bf2fb85b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt index 8e3e34f3ff..34561c55ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerEqualSplitterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 9bc92d7a46..4b9ca7bd77 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt index a4bc7e9132..3b9c8d017a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHan import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt index b2eba387c8..a58d3096fb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt index 1f116ab676..b046b3c28e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.transport.node.NodeFactory -import net.horizonsend.ion.server.features.transport.node.getNeighborNodes -import net.horizonsend.ion.server.features.transport.node.handleMerges -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.power.SolarPanelNode.Companion.matchesSolarPanelStructure +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode.Companion.matchesSolarPanelStructure +import net.horizonsend.ion.server.features.transport.node.util.NodeFactory +import net.horizonsend.ion.server.features.transport.node.util.getNeighborNodes +import net.horizonsend.ion.server.features.transport.node.util.handleMerges import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt index 4d4db86786..658e350665 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.separateNode +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.util.separateNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt index e07c8fc7c5..db5a5277b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node.power +package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.general.JunctionNode -import net.horizonsend.ion.server.features.transport.node.manager.node.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt similarity index 83% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt index 58be1e9d2d..030f8198cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.transport.node +package net.horizonsend.ion.server.features.transport.node.util -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.data.BlockData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index fad4dbbc47..63d5d24b3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -1,6 +1,7 @@ -package net.horizonsend.ion.server.features.transport.node +package net.horizonsend.ion.server.features.transport.node.util import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.node.TransportNode import kotlin.math.roundToInt inline fun getNetworkDestinations(origin: TransportNode, check: (T) -> Boolean): ObjectOpenHashSet { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt index 2c9a8273f7..586912d07e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt @@ -1,7 +1,8 @@ -package net.horizonsend.ion.server.features.transport.node +package net.horizonsend.ion.server.features.transport.node.util import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.node.manager.node.NodeManager +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt index a051ae5f05..7adff983f6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Extractors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.old import com.google.gson.Gson import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.transport.pipe.Pipes -import net.horizonsend.ion.server.features.transport.pipe.filter.FilterItemData -import net.horizonsend.ion.server.features.transport.pipe.filter.Filters +import net.horizonsend.ion.server.features.transport.old.pipe.Pipes +import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData +import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonMetricsCollection.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/IonMetricsCollection.kt similarity index 83% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonMetricsCollection.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/IonMetricsCollection.kt index d09c016972..d5e7f36da8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonMetricsCollection.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/IonMetricsCollection.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.old import dev.cubxity.plugins.metrics.api.metric.collector.CollectorCollection import dev.cubxity.plugins.metrics.api.metric.collector.Histogram diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfig.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/TransportConfig.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfig.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/TransportConfig.kt index bd89be637f..0d3439d597 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfig.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/TransportConfig.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.old import kotlinx.serialization.Serializable import net.horizonsend.ion.common.utils.configuration.Configuration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt similarity index 99% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt index c7cfde98a2..a9a60a9974 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/Wires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.old import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader @@ -130,7 +130,7 @@ object Wires : IonServerComponent() { } override fun onDisable() { - if (::thread.isInitialized) thread.shutdown() + if (Wires::thread.isInitialized) thread.shutdown() } fun isAnyWire(material: Material) = when (material) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/PipeChainData.kt similarity index 72% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/PipeChainData.kt index 96a46aae46..4eaddc4de0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/PipeChainData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/PipeChainData.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.transport.pipe +package net.horizonsend.ion.server.features.transport.old.pipe -import net.horizonsend.ion.server.features.transport.pipe.filter.FilterItemData +import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt index 28d0266f42..9957033074 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/Pipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.pipe +package net.horizonsend.ion.server.features.transport.old.pipe import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem @@ -6,11 +6,11 @@ import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer import net.horizonsend.ion.server.features.machine.GeneratorFuel -import net.horizonsend.ion.server.features.transport.Extractors -import net.horizonsend.ion.server.features.transport.pipe.filter.FilterData -import net.horizonsend.ion.server.features.transport.pipe.filter.FilterItemData -import net.horizonsend.ion.server.features.transport.pipe.filter.Filters -import net.horizonsend.ion.server.features.transport.transportConfig +import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterData +import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData +import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters +import net.horizonsend.ion.server.features.transport.old.transportConfig import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.MATERIALS import net.horizonsend.ion.server.miscellaneous.utils.Tasks diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterData.kt similarity index 72% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterData.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterData.kt index 51104dcc61..0ffd750fd7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterData.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.pipe.filter +package net.horizonsend.ion.server.features.transport.old.pipe.filter import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterDataKey.kt similarity index 68% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterDataKey.kt index 7689b2d0ad..e850abd40d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterDataKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterDataKey.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.pipe.filter +package net.horizonsend.ion.server.features.transport.old.pipe.filter import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import java.util.UUID diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterItemData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterItemData.kt similarity index 88% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterItemData.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterItemData.kt index d1426d72ec..656728bcb7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/FilterItemData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterItemData.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.pipe.filter +package net.horizonsend.ion.server.features.transport.old.pipe.filter import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt index e486db2954..de4344e959 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/pipe/filter/Filters.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.pipe.filter +package net.horizonsend.ion.server.features.transport.old.pipe.filter import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader @@ -96,11 +96,11 @@ object Filters : IonServerComponent() { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun onPistonMove(event: BlockPistonExtendEvent) { - event.blocks.forEach(::invalidateBlock) + event.blocks.forEach(Filters::invalidateBlock) } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun onPistonMove(event: BlockPistonRetractEvent) { - event.blocks.forEach(::invalidateBlock) + event.blocks.forEach(Filters::invalidateBlock) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index bba53e6c1e..644d7f9746 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -90,13 +90,13 @@ import net.horizonsend.ion.server.features.starship.hyperspace.Hyperspace import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeacons import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCooldown import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields -import net.horizonsend.ion.server.features.transport.Extractors import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.TransportConfig -import net.horizonsend.ion.server.features.transport.Wires import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids -import net.horizonsend.ion.server.features.transport.pipe.Pipes -import net.horizonsend.ion.server.features.transport.pipe.filter.Filters +import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.old.TransportConfig +import net.horizonsend.ion.server.features.transport.old.Wires +import net.horizonsend.ion.server.features.transport.old.pipe.Pipes +import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters import net.horizonsend.ion.server.features.tutorial.Tutorials import net.horizonsend.ion.server.features.waypoint.WaypointManager import net.horizonsend.ion.server.features.world.IonWorld From f74b8ed1db7e8b1ba310eb7dde8dbf94407d166a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Sep 2024 01:07:53 -0500 Subject: [PATCH 180/500] fix end rod bug --- .../ion/server/features/transport/node/type/MultiNode.kt | 4 +++- .../features/transport/node/type/general/LinearNode.kt | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 12f3541721..731ccf22bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -119,7 +119,7 @@ abstract class MultiNode, Z: MultiNode> : Tran /** * Places the set of positions into the network as this type of node. **/ - fun ofPositions(positions: Set) { + open fun ofPositions(positions: Set): Self { @Suppress("UNCHECKED_CAST") val newNode = type.newInstance(manager) as Self @@ -127,6 +127,8 @@ abstract class MultiNode, Z: MultiNode> : Tran newNode.addPosition(it) newNode.buildRelations(it) } + + return newNode } abstract fun addBack(position: BlockKey) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index 2e854248eb..48d47a2f70 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -49,5 +49,11 @@ abstract class LinearNode, B: LinearNode< return positions.size // Always in one end and out the other } + override fun ofPositions(positions: Set): B { + val new = super.ofPositions(positions) + new.axis = axis + return new + } + override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationships.size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } From 998abbbc472aa234b127896c85e2468fff440c0b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Sep 2024 01:22:45 -0500 Subject: [PATCH 181/500] implement fluid tank mechanics --- .../fluid/storage/FluidStorageMultiblock.kt | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 64b1972dc2..bcea87aca1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.storage import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SimpleFluidDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity @@ -8,6 +10,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidSt import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.UnlimitedInternalStorage import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -15,8 +18,7 @@ import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.World import org.bukkit.block.BlockFace -abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), - EntityMultiblock { +abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityMultiblock { override val name: String = "tank" override val alternativeDetectionNames: Array = arrayOf("gastank", "fluidtank") @@ -42,5 +44,30 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), structureDirection: BlockFace, ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity { override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + SimpleFluidDisplay(mainStorage, +0.0, -0.0, +0.0, 0.45f), + ).register() + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun storeAdditionalData(store: PersistentMultiblockData) { + val rawStorage = store.getAdditionalDataRaw() + storeFluidData(rawStorage, rawStorage.adapterContext) + } } } From e1202602a187897a14bc5404449ee299e45a8e6d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Sep 2024 01:33:18 -0500 Subject: [PATCH 182/500] display improvements --- .../modular/display/fluid/FluidDisplay.kt | 8 ++++---- .../display/fluid/SimpleFluidDisplay.kt | 10 ++++++++-- .../display/fluid/SplitFluidDisplay.kt | 19 +++++++++++++++++++ .../fluid/storage/FluidStorageMultiblock.kt | 4 ++-- 4 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt index 422ae20c6f..7821e8b2d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt @@ -9,7 +9,7 @@ import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor abstract class FluidDisplay( - val storage: StorageContainer, + val container: StorageContainer, offsetLeft: Double, offsetUp: Double, offsetBack: Double, @@ -20,15 +20,15 @@ abstract class FluidDisplay( } override fun register() { - storage.storage.registerUpdateHandler(updateHandler) + container.storage.registerUpdateHandler(updateHandler) } override fun deRegister() { - storage.storage.removeUpdateHandler(updateHandler) + container.storage.removeUpdateHandler(updateHandler) } protected fun formatFluid(): Component { - val amount = storage.storage.getAmount() + val amount = container.storage.getAmount() return ofChildren(text(amount, NamedTextColor.GOLD), text("L", NamedTextColor.DARK_GRAY)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index 10f07121b0..0affcaa915 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -3,8 +3,10 @@ package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.space +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.TextDecoration class SimpleFluidDisplay( storage: StorageContainer, @@ -14,6 +16,10 @@ class SimpleFluidDisplay( scale: Float ) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { - return ofChildren(formatFluid(), space(), storage.storage.getStoredFluid()?.displayName ?: empty()) + return ofChildren(formatFluid(), space(), container.storage.getStoredFluid()?.displayName ?: empty) + } + + companion object { + val empty = text("Empty", NamedTextColor.GRAY, TextDecoration.ITALIC) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt new file mode 100644 index 0000000000..f34543b5fa --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt @@ -0,0 +1,19 @@ +package net.horizonsend.ion.server.features.client.display.modular.display.fluid + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SimpleFluidDisplay.Companion.empty +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.newline + +class SplitFluidDisplay( + storage: StorageContainer, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + scale: Float +) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { + override fun getText(): Component { + return ofChildren(container.storage.getStoredFluid()?.displayName ?: empty, newline(), formatFluid()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index bcea87aca1..10cf073189 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid.storage import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SimpleFluidDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SplitFluidDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity @@ -46,7 +46,7 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, - SimpleFluidDisplay(mainStorage, +0.0, -0.0, +0.0, 0.45f), + SplitFluidDisplay(mainStorage, +0.0, -0.0, +0.0, 0.45f), ).register() override fun onLoad() { From 620bd32ec5dc6a33e1987a948efc4a4de2fa253f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Sep 2024 02:10:51 -0500 Subject: [PATCH 183/500] async multiblock scheduler --- .../server/command/admin/IonChunkCommand.kt | 1 - .../features/multiblock/MultiblockTicking.kt | 53 +++++++++++++++++++ .../ticked/AsyncTickingMultiblockEntity.kt | 7 +-- .../manager/ChunkMultiblockManager.kt | 4 ++ .../multiblock/manager/MultiblockManager.kt | 28 ---------- .../manager/ShipMultiblockManager.kt | 14 +++-- .../type/fluid/ElectrolysisMultiblock.kt | 2 +- .../collector/PipedGasCollectorMultiblock.kt | 2 +- .../starship/DeactivatedPlayerStarships.kt | 2 +- .../ion/server/features/starship/Starship.kt | 2 - .../node/manager/ShipTransportManager.kt | 5 +- .../ion/server/features/world/IonWorld.kt | 5 -- .../features/world/chunk/ChunkRegion.kt | 16 ------ .../miscellaneous/registrations/Components.kt | 2 + 14 files changed, 76 insertions(+), 67 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 471c5783c4..4c7f858391 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -102,7 +102,6 @@ object IonChunkCommand : SLCommand() { val ionChunk = sender.chunk.ion() sender.information("Chunk: $ionChunk") - sender.information("Region: ${ionChunk.region}, last ticked: ${ionChunk.region.lastTicked}") sender.information("World has: ${ionChunk.world.ion.regionPositions.values.distinct().size} unique regions") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt new file mode 100644 index 0000000000..cb5df5bbd3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt @@ -0,0 +1,53 @@ +package net.horizonsend.ion.server.features.multiblock + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors + +object MultiblockTicking : IonServerComponent() { + private val managers = ArrayList() + + private lateinit var executor: ExecutorService + + override fun onEnable() { + executor = Executors.newCachedThreadPool(Tasks.namedThreadFactory("asnc-multiblock-worker")) + + Tasks.asyncRepeat(1L, 1L, ::tickAsyncMultiblocks) + Tasks.syncRepeat(1L, 1L, ::tickSyncMultiblocks) + } + + override fun onDisable() { + if (::executor.isInitialized) executor.shutdown() + } + + private fun tickSyncMultiblocks() = managers.forEach { manager -> + for ((key, syncTicking) in manager.syncTickingMultiblockEntities) runCatching { + if (SyncTickingMultiblockEntity.preTick(syncTicking as MultiblockEntity)) syncTicking.tick() + }.onFailure { e -> + log.warn("Exception ticking multiblock ${syncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") + e.printStackTrace() + } + } + + private fun tickAsyncMultiblocks() = managers.forEach { manager -> + for ((key, asyncTicking) in manager.asyncTickingMultiblockEntities) runCatching { + if (SyncTickingMultiblockEntity.preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() + }.onFailure { e -> + log.warn("Exception ticking async multiblock ${asyncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") + e.printStackTrace() + } + } + + fun registerMultiblockManager(manager: MultiblockManager) { + managers.add(manager) + } + + fun removeMultiblockManager(manager: MultiblockManager) { + managers.remove(manager) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt index 97c7231332..d7b0d6d406 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/AsyncTickingMultiblockEntity.kt @@ -7,10 +7,5 @@ interface AsyncTickingMultiblockEntity : TickedMultiblockEntityParent { /** * The logic that is run upon world tick **/ - suspend fun tickAsync() - - /** - * - **/ - fun shouldAsyncCheckIntegrity(): Boolean = true + fun tickAsync() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 014325d9ee..3d1863a7c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.node.manager.NodeManager @@ -35,6 +36,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag init { loadMultiblocks() + MultiblockTicking.registerMultiblockManager(this) } /** @@ -92,5 +94,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag multiblockEntities.values.forEach { it.onUnload() } + + MultiblockTicking.removeMultiblockManager(this) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index a9ec12936e..57d7d700d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.manager -import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity @@ -14,7 +12,6 @@ import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManag import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.World import org.bukkit.block.BlockFace @@ -36,13 +33,6 @@ abstract class MultiblockManager(val log: Logger) { abstract fun markChanged() - /** - * Logic upon the chunk being ticked - **/ - fun tick() { - tickAllMultiblocks() - } - fun getAllMultiblockEntities() = multiblockEntities abstract fun getNetwork(type: NetworkType): NodeManager @@ -87,24 +77,6 @@ abstract class MultiblockManager(val log: Logger) { return entity } - private fun tickAllMultiblocks() { - for ((key, syncTicking) in syncTickingMultiblockEntities) runCatching { - if (SyncTickingMultiblockEntity.preTick(syncTicking as MultiblockEntity)) syncTicking.tick() - }.onFailure { e -> - log.warn("Exception ticking multiblock ${syncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") - e.printStackTrace() - } - - for ((key, asyncTicking) in asyncTickingMultiblockEntities) runCatching { - MultiblockAccess.multiblockCoroutineScope.launch { - if (SyncTickingMultiblockEntity.preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() - } - }.onFailure { e -> - log.warn("Exception ticking async multiblock ${asyncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") - e.printStackTrace() - } - } - /** * Add a new multiblock to the chunk data **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 43bf64bbad..70fac22054 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity @@ -34,6 +35,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe init { loadEntities() + MultiblockTicking.registerMultiblockManager(this) } fun loadEntities() { @@ -61,11 +63,15 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe } } + fun release() { + MultiblockTicking.removeMultiblockManager(this) + } + fun releaseEntities() { - val manager = world.ion.multiblockManager + val worldManager = world.ion.multiblockManager for ((key, multiblockEntity) in multiblockEntities) { - val network = manager.getChunkManager(key) ?: continue + val network = worldManager.getChunkManager(key) ?: continue // If it was lost, don't place it back if (!multiblockEntity.isIntact(checkSign = true)) { @@ -78,7 +84,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe } for ((key, multiblockEntity) in syncTickingMultiblockEntities) { - val network = manager.getChunkManager(key) ?: continue + val network = worldManager.getChunkManager(key) ?: continue // If it was lost, don't place it back if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { @@ -90,7 +96,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe } for ((key, multiblockEntity) in asyncTickingMultiblockEntities) { - val network = manager.getChunkManager(key) ?: continue + val network = worldManager.getChunkManager(key) ?: continue // If it was lost, don't place it back if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index c46cc5307b..930163b4d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -241,7 +241,7 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock) in starship.carriedShips) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index f0952d3c5b..9c3c5cea1f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -140,8 +140,6 @@ class Starship( /** Called on each server tick. */ fun tick() { controller.tick() - multiblockManager.tick() - transportManager.tick() subsystems.forEach { it.tick() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index fc5c2b1b3c..ae9fb44270 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.manager.holders.ShipNetworkHolder class ShipTransportManager(val starship: Starship) : TransportManager() { @@ -13,11 +14,11 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { } fun load() { - + NewTransport.registerTransportManager(this) } fun release() { - + NewTransport.removeTransportManager(this) } fun displace(movement: StarshipMovement) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 8eebf450bb..0f14d314c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -198,11 +198,6 @@ class IonWorld private constructor( val result = runCatching(starship::tick).exceptionOrNull() ?: continue log.warn("Exception while ticking starship!", result) } - - for (region in ionWorld.chunkRegions) { - val result = runCatching { region.tick() }.exceptionOrNull() ?: continue - log.warn("Exception while ticking chunk region!", result) - } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index f06bb8db2a..d62a5c4ca1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -17,22 +17,6 @@ class ChunkRegion(val world: IonWorld) { val size get() = chunks.values.size - fun tickChunkTransport() { - for ((_, chunk) in chunks) { - chunk.multiblockManager.tick() - } - } - - var lastTicked: Long = 0 - - fun tick() { - lastTicked = System.currentTimeMillis() - - tickChunkTransport() - - for ((key, chunk) in chunks) chunk.tick() - } - fun removeChunk(chunk: IonChunk) { chunks.remove(chunk.locationKey) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 644d7f9746..0c99563242 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -39,6 +39,7 @@ import net.horizonsend.ion.server.features.misc.Shuttles import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration +import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration @@ -145,6 +146,7 @@ val components: List = listOf( MultiblockRecipes, MultiblockRegistration, MultiblockAccess, + MultiblockTicking, PowerMachines, AreaShields, From d9a7cda139ae6f5df5ef2aca8883b5dd86db29da Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Sep 2024 02:41:35 -0500 Subject: [PATCH 184/500] better set fluid command --- .../net/horizonsend/ion/server/command/qol/SetFluidCommand.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt index 4dfd8a29f3..ddc2fc8e04 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt @@ -33,7 +33,7 @@ object SetFluidCommand : SLCommand() { } @Default - @CommandCompletion("0|1000|500000|2147483647 true|false") + @CommandCompletion("@fluids 0|1000|500000|2147483647 main") @Suppress("unused") fun onSetFluid(sender: Player, fluid: PipedFluid, amount: Int, storeName: String) { val selection = runCatching { sender.getSelection() }.getOrNull() ?: fail { "You must make a selection!" } From 9801824967895b2dd380c9d4874cfef6f3a3a37a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Sep 2024 14:22:50 -0500 Subject: [PATCH 185/500] multiblock display names --- .../items/misc/PackagedMultiblockItem.kt | 82 +++++++++++++++++++ .../multiblock/type/DisplayNameMultilblock.kt | 13 +++ .../type/fluid/ElectrolysisMultiblock.kt | 13 ++- 3 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt new file mode 100644 index 0000000000..13f52c9558 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt @@ -0,0 +1,82 @@ +package net.horizonsend.ion.server.features.custom.items.misc + +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.PrePackaged +import net.horizonsend.ion.server.features.multiblock.PrePackaged.getPackagedData +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GRAY +import net.kyori.adventure.text.format.NamedTextColor.WHITE +import net.kyori.adventure.text.format.TextDecoration.ITALIC +import org.bukkit.Material +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType +import java.util.Locale + +object PackagedMultiblockItem : CustomItem("PACKAGED_MULTIBLOCK") { + override fun constructItemStack(): ItemStack { + val base = ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + it.persistentDataContainer.set(CUSTOM_ITEM, PersistentDataType.STRING, identifier) + it.displayName(text("Pre-Packaged Multiblock").decoration(ITALIC, false)) + } + + return base + } + + fun constructFor(multiblock: Multiblock): ItemStack { + val base = constructItemStack() + + return base.updateMeta { + PrePackaged.packageData(PrePackaged.PackagedMultiblockData(multiblock), it.persistentDataContainer) + it.displayName(text() + .decoration(ITALIC, false) + .color(WHITE) + .append(text("Pre-packaged ")) + .append(multiblock.getDisplayName()) + .build() + ) + it.lore(listOf( + text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", GRAY).decoration(ITALIC, false), + text("Variant: ${multiblock.javaClass.simpleName}", GRAY).decoration(ITALIC, false) + )) + } + } + + override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + if (itemStack.type.isAir) return + + val packagedData = getPackagedData(itemStack) ?: run { + livingEntity.userError("The packaged multiblock has no data!") + return + } + + if (livingEntity !is Player) return + + if (event == null) return + + val origin = PrePackaged.getOriginFromPlacement( + event.clickedBlock ?: return, + livingEntity.facing, + packagedData.multiblock.shape + ) + + val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.multiblock.shape) + + if (obstructions.isNotEmpty()) { + livingEntity.userError("Placement is obstructed!") + livingEntity.highlightBlocks(obstructions, 50L) + return + } + + PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData) + livingEntity.inventory.remove(itemStack) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt new file mode 100644 index 0000000000..f95984f661 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.multiblock.type + +import net.horizonsend.ion.common.utils.text.toComponent +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.kyori.adventure.text.Component + +interface DisplayNameMultilblock { + val displayName: Component + + companion object { + fun Multiblock.getDisplayName() = if (this is DisplayNameMultilblock) displayName else javaClass.simpleName.toComponent() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 930163b4d2..cc7a3c5153 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay @@ -18,6 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane @@ -38,7 +40,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.NamedTextColor.GOLD +import net.kyori.adventure.text.format.NamedTextColor.RED import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -48,13 +51,15 @@ import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { +object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { override val name: String = "ElectrolysisMultiblock" override val alternativeDetectionNames: Array = arrayOf("Electrolysis") + override val displayName: Component = ofChildren(text("Electrolysis ", GOLD), text("Machine", RED)) + override val signText: Array = arrayOf( - text("Electrolysis", NamedTextColor.GOLD), - text("Machine", NamedTextColor.RED), + text("Electrolysis", GOLD), + text("Machine", RED), null, null ) From 51e21d2c5477ea1fa0fc8ad4b70934c696aff888 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 21 Sep 2024 02:48:54 -0500 Subject: [PATCH 186/500] multiblock entity saving / loading / migration improvements --- .../features/multiblock/MultiblockAccess.kt | 4 +- .../features/multiblock/MultiblockEntities.kt | 68 ++++++++++++++++--- .../features/multiblock/MultiblockTicking.kt | 13 +++- .../multiblock/entity/MultiblockEntity.kt | 15 +++- .../entity/PersistentMultiblockData.kt | 2 +- .../entity/type/LegacyMultiblockEntity.kt | 9 +++ .../entity/type/ProcessingMultiblockEntity.kt | 3 +- .../type/fluids/BasicFluidStoringEntity.kt | 6 +- .../entity/type/fluids/FluidStoringEntity.kt | 11 +-- .../manager/ChunkMultiblockManager.kt | 12 +++- .../multiblock/manager/MultiblockManager.kt | 6 +- .../manager/ShipMultiblockManager.kt | 1 + .../defense/passive/areashield/AreaShield.kt | 3 +- .../type/fluid/ElectrolysisMultiblock.kt | 6 +- .../collector/PipedGasCollectorMultiblock.kt | 6 +- .../fluid/storage/FluidStorageMultiblock.kt | 6 +- .../type/power/charger/ChargerMultiblock.kt | 3 +- .../type/power/storage/PowerBankMultiblock.kt | 3 +- .../type/power/storage/PowerCellMultiblock.kt | 3 +- .../server/features/transport/IonChangeSet.kt | 22 +++--- .../multiblock/MultiblockEntityInitializer.kt | 5 +- .../miscellaneous/registrations/Listeners.kt | 2 + 22 files changed, 148 insertions(+), 61 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index 8817a62975..efdadfba41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -180,9 +180,7 @@ object MultiblockAccess : IonServerComponent() { val chunkX = x.shr(4) val chunkZ = z.shr(4) - world.ion.getChunk(chunkX, chunkZ)?.let { - it.region.launch { it.multiblockManager.handleNewMultiblockEntity(multiblock, x, y, z, structureDirection) } - } + world.ion.getChunk(chunkX, chunkZ)?.multiblockManager?.handleNewMultiblockEntity(multiblock, x, y, z, structureDirection) } return true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 4e78d1d6cd..43c99903b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -1,18 +1,29 @@ package net.horizonsend.ion.server.features.multiblock +import com.destroystokyo.paper.event.server.ServerTickEndEvent import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA +import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.Sign +import org.bukkit.event.EventHandler -object MultiblockEntities { +/** + * Provides utility functions for multiblock entities, and handles sign backups + **/ +object MultiblockEntities : SLEventListener() { /** * **/ fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { - val ionChunk = getIonChunk(world, x, y, z) ?: return null + val ionChunk = getIonChunk(world, x, z) ?: return null return ionChunk.multiblockManager[x, y, z] } @@ -24,31 +35,66 @@ object MultiblockEntities { /** * Add a new multiblock entity to the chunk **/ - fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, entity: (MultiblockManager) -> MultiblockEntity): Boolean { - val ionChunk = getIonChunk(world, x, y, z) ?: return false + fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, createEntity: (MultiblockManager) -> MultiblockEntity): MultiblockEntity? { + val ionChunk = getIonChunk(world, x, z) ?: return null - ionChunk.region.launch { - val manager = ionChunk.multiblockManager + val manager = ionChunk.multiblockManager - manager.addMultiblockEntity(entity(manager), save = true) - } + val entity = createEntity(manager) + manager.addMultiblockEntity(entity, save = true) - return true + return entity } /** * **/ fun removeMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { - val ionChunk = getIonChunk(world, x, y, z) ?: return null + val ionChunk = getIonChunk(world, x, z) ?: return null return ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) } - private fun getIonChunk(world: World, x: Int, y: Int, z: Int): IonChunk? { + private fun getIonChunk(world: World, x: Int, z: Int): IonChunk? { val chunkX = x.shr(4) val chunkZ = z.shr(4) return world.ion.getChunk(chunkX, chunkZ) } + + fun loadFromData(multiblock: EntityMultiblock, manager: MultiblockManager, stored: PersistentMultiblockData): T { + return multiblock.createEntity(manager, stored, manager.world, stored.x, stored.y, stored.z, stored.signOffset) + } + + fun loadFromSign(sign: Sign) { + val data = sign.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return + val origin = MultiblockEntity.getOriginFromSign(sign) + val multiblockType = MultiblockAccess.getFast(sign) as? EntityMultiblock<*> ?: return + + // In case it moved + data.x = origin.x + data.y = origin.y + data.z = origin.z + data.signOffset = sign.getFacing().oppositeFace + + setMultiblockEntity(sign.world, origin.x, origin.y, origin.z) { manager -> + loadFromData(multiblockType, manager, data) + } + } + + @EventHandler + fun onTickEnd(event: ServerTickEndEvent) { + if (event.timeRemaining < 0) return + + val sorted = MultiblockTicking.getAllMultiblockManagers() + for (manager in sorted) { + if (manager.getSignUnsavedTime() < 5000L) continue + + for (keyEntity in manager.getAllMultiblockEntities()) { + if (event.timeRemaining < 0) return + keyEntity.value.saveToSign() + } + manager.markSignSaved() + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt index cb5df5bbd3..bbe2d28add 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt @@ -25,7 +25,7 @@ object MultiblockTicking : IonServerComponent() { if (::executor.isInitialized) executor.shutdown() } - private fun tickSyncMultiblocks() = managers.forEach { manager -> + private fun tickSyncMultiblocks() = iterateManagers { manager -> for ((key, syncTicking) in manager.syncTickingMultiblockEntities) runCatching { if (SyncTickingMultiblockEntity.preTick(syncTicking as MultiblockEntity)) syncTicking.tick() }.onFailure { e -> @@ -34,7 +34,7 @@ object MultiblockTicking : IonServerComponent() { } } - private fun tickAsyncMultiblocks() = managers.forEach { manager -> + private fun tickAsyncMultiblocks() = iterateManagers { manager -> for ((key, asyncTicking) in manager.asyncTickingMultiblockEntities) runCatching { if (SyncTickingMultiblockEntity.preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() }.onFailure { e -> @@ -43,6 +43,13 @@ object MultiblockTicking : IonServerComponent() { } } + fun iterateManagers(task: (MultiblockManager) -> Unit) { + @Suppress("UNCHECKED_CAST") + val clone = managers.clone() as ArrayList + + clone.forEach(task) + } + fun registerMultiblockManager(manager: MultiblockManager) { managers.add(manager) } @@ -50,4 +57,6 @@ object MultiblockTicking : IonServerComponent() { fun removeMultiblockManager(manager: MultiblockManager) { managers.remove(manager) } + + fun getAllMultiblockManagers() = managers } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index ca21304041..9a72f47f29 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -15,6 +16,7 @@ import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataAdapterContext /** * @param manager The multiblock manager that this is registered to @@ -86,7 +88,7 @@ abstract class MultiblockEntity( /** * Stores any additional data for this multiblock (e.g. power, owner, etc) **/ - protected open fun storeAdditionalData(store: PersistentMultiblockData) {} + protected open fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) {} /** * Returns the serializable data for this multiblock entity @@ -97,11 +99,20 @@ abstract class MultiblockEntity( **/ fun store(): PersistentMultiblockData { val store = PersistentMultiblockData(x, y, z, multiblock, structureDirection) - storeAdditionalData(store) + storeAdditionalData(store, store.getAdditionalDataRaw().adapterContext) return store } + fun saveToSign() { + val sign = getSign() ?: return + val pdc = sign.persistentDataContainer + + val data = store() + pdc.set(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData, data) + sign.update() + } + fun isSignLoaded(): Boolean { val signDirection = structureDirection.oppositeFace val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt index 5766ebc376..ebdbe5e07e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/PersistentMultiblockData.kt @@ -20,7 +20,7 @@ import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.STRING import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER -class PersistentMultiblockData(val x: Int, val y: Int, val z: Int, val type: Multiblock, val signOffset: BlockFace) { +class PersistentMultiblockData(var x: Int, var y: Int, var z: Int, val type: Multiblock, var signOffset: BlockFace) { constructor(x: Int, y: Int, z: Int, type: Multiblock, signOffset: BlockFace, additionalData: PersistentDataContainer) : this(x, y, z, type, signOffset) { this.additionalData = additionalData } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt new file mode 100644 index 0000000000..9d1c6267f7 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import org.bukkit.block.Sign + +interface LegacyMultiblockEntity { + fun loadFromSign(sign: Sign) { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt index d1b632ef7b..0b7763358f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataType /** @@ -45,7 +46,7 @@ abstract class ProcessingMultiblockEntity( currentProgress++ } - override fun storeAdditionalData(store: PersistentMultiblockData) { + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { store.addAdditionalData(NamespacedKeys.PROCESSING_PROGRESS, PersistentDataType.INTEGER, currentProgress) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index da5caedeb6..b51c86af94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.kyori.adventure.text.Component import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataAdapterContext /** * A simple fluid storing entity with a single main storage @@ -32,8 +33,7 @@ abstract class BasicFluidStoringEntity( val mainStorage by lazy { getStorage(NamespacedKeys.MAIN_STORAGE) } - override fun storeAdditionalData(store: PersistentMultiblockData) { - val rawStorage = store.getAdditionalDataRaw() - storeFluidData(rawStorage, rawStorage.adapterContext) + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + storeFluidData(store, adapterContext) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index f21e090f71..f03f99558e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -13,7 +13,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.kyori.adventure.text.Component import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { @@ -67,14 +66,10 @@ interface FluidStoringEntity { fun getStorage(key: NamespacedKey): StorageContainer = capacities.first { it.namespacedKey == key } - fun storeFluidData(destination: PersistentDataContainer, context: PersistentDataAdapterContext) { + fun storeFluidData(destination: PersistentMultiblockData, context: PersistentDataAdapterContext) { val storages = context.newPersistentDataContainer() - - capacities.forEach { - it.save(storages) - } - - destination.set(STORAGES, TAG_CONTAINER, storages) + capacities.forEach { it.save(storages) } + destination.addAdditionalData(STORAGES, TAG_CONTAINER, storages) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 3d1863a7c3..c67a3c3664 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock @@ -26,6 +27,15 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag saveMultiblocks(chunk.inner.persistentDataContainer.adapterContext) } + private var lastSaved = System.currentTimeMillis() + override fun getSignUnsavedTime(): Long { + return System.currentTimeMillis() - lastSaved + } + + override fun markSignSaved() { + lastSaved = System.currentTimeMillis() + } + override fun markChanged() { chunk.inner.minecraft.isUnsaved = true } @@ -83,7 +93,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag val multiblock = stored.type as EntityMultiblock<*> - val entity = multiblock.createEntity(this, stored, chunk.inner.world, stored.x, stored.y, stored.z, stored.signOffset) + val entity = MultiblockEntities.loadFromData(multiblock, this, stored) // No need to save a load addMultiblockEntity(entity, save = false) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 57d7d700d0..a811514aea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -37,6 +37,9 @@ abstract class MultiblockManager(val log: Logger) { abstract fun getNetwork(type: NetworkType): NodeManager + abstract fun getSignUnsavedTime(): Long + open fun markSignSaved() {} + /** * Handles the addition of a multiblock entity **/ @@ -80,8 +83,7 @@ abstract class MultiblockManager(val log: Logger) { /** * Add a new multiblock to the chunk data **/ - suspend fun handleNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace) { - // Allow smart cast + fun handleNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace) { multiblock as Multiblock // Abort process if one already exists, so it's not overwritten diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 70fac22054..4a46d6e56d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -27,6 +27,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override val world get() = starship.world override fun save() {} + override fun getSignUnsavedTime(): Long = 0 override fun markChanged() {} override fun getNetwork(type: NetworkType): NodeManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 7daa1a94e8..099cde7a41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -25,6 +25,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataAdapterContext import java.util.concurrent.TimeUnit abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { @@ -128,7 +129,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< displayHandler.displace(movement) } - override fun storeAdditionalData(store: PersistentMultiblockData) { + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index cc7a3c5153..d9e45001b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -50,6 +50,7 @@ import org.bukkit.block.data.Bisected.Half.TOP import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataAdapterContext object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { override val name: String = "ElectrolysisMultiblock" @@ -254,9 +255,8 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock { override val name: String = "tank" @@ -65,9 +66,8 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM displayHandler.displace(movement) } - override fun storeAdditionalData(store: PersistentMultiblockData) { - val rawStorage = store.getAdditionalDataRaw() - storeFluidData(rawStorage, rawStorage.adapterContext) + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + storeFluidData(store, adapterContext) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 032288e747..47e56ce360 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -26,6 +26,7 @@ import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock { protected abstract val tierMaterial: Material @@ -178,7 +179,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere displayHandler.displace(movement) } - override fun storeAdditionalData(store: PersistentMultiblockData) { + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index b41c757aa0..d364f81db5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -16,6 +16,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataAdapterContext abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { abstract val tierMaterial: Material @@ -137,7 +138,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM displayHandler.displace(movement) } - override fun storeAdditionalData(store: PersistentMultiblockData) { + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 9f29cf7e40..7455179ac6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputN import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataAdapterContext object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "powercell" @@ -95,7 +96,7 @@ object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock + val entity = MultiblockEntities.setMultiblockEntity(sign.world, x, y, z) { manager -> multiblock.createEntity( manager, PersistentMultiblockData(x, y, z, multiblock, multiblockDirection), @@ -33,6 +34,8 @@ object MultiblockEntityInitializer : SignDataFixer { multiblockDirection ) } + + if (entity is LegacyMultiblockEntity) entity.loadFromSign(sign) } override val dataVersion: Int = 1 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index d0cbd09474..22a5279c98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemListeners import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporterManager import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners import net.horizonsend.ion.server.features.machine.CryoPods +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners @@ -86,6 +87,7 @@ val listeners: List = listOf( PersonalTransporterManager, TransportManager, GlobalNodeManager, + MultiblockEntities, // Achievement Listeners AchievementListeners(), From 7a06bf2e2894d185a1629c6a98b57b7da9055d64 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 21 Sep 2024 02:51:05 -0500 Subject: [PATCH 187/500] remove multiblock entities if setting air --- .../ion/server/features/transport/IonChangeSet.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt index 3c9fb6fe4f..cb6a14b01d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt @@ -32,6 +32,7 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { ) if (type.isWallSign) processMultiblock(x, y, z) + if (type.isAir) removeMultiblock(x, y, z) } } @@ -42,6 +43,10 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { } } + private fun removeMultiblock(x: Int, y: Int, z: Int) { + MultiblockEntities.removeMultiblockEntity(bukkitWorld, x, y, z) + } + private var recording: Boolean = true override fun isRecordingChanges(): Boolean { From 53b93f450d074c6eed7457228bad9ecb296300df Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 21 Sep 2024 13:21:20 -0500 Subject: [PATCH 188/500] remove bound power inputs, allow additional ones around signs --- .../features/multiblock/MultiblockEntities.kt | 16 ++++++++ .../type/power/PoweredMultiblockEntity.kt | 16 -------- .../multiblock/manager/MultiblockManager.kt | 6 --- .../defense/passive/areashield/AreaShield.kt | 2 - .../type/fluid/ElectrolysisMultiblock.kt | 3 -- .../type/power/charger/ChargerMultiblock.kt | 2 - .../type/power/storage/PowerBankMultiblock.kt | 4 -- .../type/power/storage/PowerCellMultiblock.kt | 4 -- .../node/manager/PowerNodeManager.kt | 41 ++----------------- .../node/type/power/PowerExtractorNode.kt | 2 +- .../node/type/power/PowerInputNode.kt | 38 +++++++++++------ 11 files changed, 46 insertions(+), 88 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 43c99903b6..6ea8f55844 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -9,6 +9,10 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.World import org.bukkit.block.Block @@ -28,6 +32,18 @@ object MultiblockEntities : SLEventListener() { return ionChunk.multiblockManager[x, y, z] } + /** + * + **/ + fun getMultiblockEntity(world: World, key: BlockKey): MultiblockEntity? { + val x = getX(key) + val y = getY(key) + val z = getZ(key) + val ionChunk = getIonChunk(world, x, z) ?: return null + + return ionChunk.multiblockManager[x, y, z] + } + fun getMultiblockEntity(origin: Block): MultiblockEntity? { return getMultiblockEntity(origin.world, origin.x, origin.y, origin.z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 9bdf395532..f13929264e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -33,19 +32,4 @@ interface PoweredMultiblockEntity { forward = powerInputOffset.z ) } - - var inputNode: PowerInputNode? - - fun bindInputNode(node: PowerInputNode) { - if (node.boundMultiblockEntity != null) return - - node.boundMultiblockEntity = this - } - - fun releaseInputNode() { - val existing = inputNode ?: return - if (existing.boundMultiblockEntity != this) return - - existing.boundMultiblockEntity = null - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index a811514aea..060292ebb0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -3,12 +3,10 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -56,10 +54,6 @@ abstract class MultiblockManager(val log: Logger) { asyncTickingMultiblockEntities[entity.locationKey] = entity } - if (entity is PoweredMultiblockEntity) { - (getNetwork(NetworkType.POWER) as PowerNodeManager).tryBindPowerNode(entity) - } - if (save) save() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 099cde7a41..53961e8a5e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -13,7 +13,6 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -99,7 +98,6 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< world: World, signDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { - override var inputNode: PowerInputNode? = null override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index d9e45001b1..1a5930aa45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -28,7 +28,6 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 @@ -220,8 +219,6 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock) : NodeManager(ho val shareFactor = shareFactors[index] ?: continue val share = shareFactor / shareFactorSum - val recipient = destination.boundMultiblockEntity - - if (recipient == null) { - // Remove this share factor from the sum, since it is not taking up any power - shareFactorSum -= shareFactor - continue - } + val recipient = destination.getPoweredEntities().randomOrNull() ?: continue val idealSend = (availableTransferPower * share).roundToInt() val toSend = minOf(idealSend, recipient.storage.getRemainingCapacity()) @@ -142,33 +133,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho return remainingPower } - override fun finalizeNodes() { - @Suppress("UNCHECKED_CAST") - val chunk = (holder as? ChunkNetworkHolder)?.manager?.chunk ?: return - chunk.multiblockManager.getAllMultiblockEntities().values.filterIsInstance().forEach(::tryBindPowerNode) - } - - /** - * Handle the addition of a new powered multiblock entity - **/ - fun tryBindPowerNode(new: PoweredMultiblockEntity) { - // All directions - val inputVec = new.getRealInputLocation() - val inputKey = toBlockKey(inputVec) - - val inputNode = getNode(inputKey) as? PowerInputNode - - if (inputNode != null) { - new.bindInputNode(inputNode) - return - } - - val (x, y, z) = inputVec - val block = getBlockIfLoaded(world, x, y, z) - if (block != null) createNodeFromBlock(block) - - val attemptTwo = getNode(inputKey) as? PowerInputNode ?: return - - new.bindInputNode(attemptTwo) + fun addPower(recipients: Collection): Int { + TODO("") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 4b9ca7bd77..9d3039376f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -71,7 +71,7 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() * Returns the amount that couldn't be removed. **/ fun drawPower(amount: Int): Int { - val entities = relationships.mapNotNull { (it.value.other as? PowerInputNode)?.boundMultiblockEntity } + val entities = relationships.mapNotNull { (it.value.other as? PowerInputNode)?.getPoweredEntities()?.randomOrNull() } //TODO var remaining = amount diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt index a58d3096fb..c57de5c2f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt @@ -1,12 +1,21 @@ package net.horizonsend.ion.server.features.transport.node.type.power +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import org.bukkit.block.data.type.WallSign import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -28,25 +37,30 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } - var boundMultiblockEntity: PoweredMultiblockEntity? = null + fun isCalling(): Boolean { + val entities = getPoweredEntities() + if (entities.isEmpty()) return false + return entities.any { it.storage.getRemainingCapacity() > 0 } + } - fun isCalling(): Boolean = boundMultiblockEntity != null && !(boundMultiblockEntity?.storage?.isFull() ?: false) + fun getPoweredEntities(): Collection { + return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableListOf()) { + val relativeKey = getRelative(position, it) + val entity = MultiblockEntities.getMultiblockEntity(manager.world, relativeKey) as? PoweredMultiblockEntity + if (entity != null) return@mapNotNullTo entity - override fun onPlace(position: BlockKey) { - super.onPlace(position) + val data = getBlockDataSafe(manager.world, getX(relativeKey), getY(relativeKey), getZ(relativeKey)) ?: return@mapNotNullTo null + if (!data.material.isWallSign) return@mapNotNullTo null + data as WallSign -// getNearbyPowerInputs().forEach { manager.tryBindPowerNode(it) } + val originKey = getRelative(relativeKey, data.facing.oppositeFace) + MultiblockEntities.getMultiblockEntity(manager.world, originKey) as? PoweredMultiblockEntity + } } -// fun getNearbyPowerInputs(): Collection { -// return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableSetOf()) { -// manager.holder.getMultiblockManager()[getRelative(position, it)] as? PoweredMultiblockEntity -// } -// } - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 0 } - override fun toString(): String = "POWER INPUT NODE. Bound to $boundMultiblockEntity" + override fun toString(): String = "POWER INPUT NODE. Bound to ${getPoweredEntities().joinToString { it.toString() }}" } From b62188edbead6aef5d9394b3937375dd4212eacb Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 21 Sep 2024 13:29:43 -0500 Subject: [PATCH 189/500] future util for packaged multis --- .../server/features/multiblock/PrePackaged.kt | 16 ++++++++++ .../multiblock/shape/BlockRequirement.kt | 5 +++- .../multiblock/shape/MultiblockShape.kt | 30 ++++++++++++------- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 5bfbaff016..dced8ef0c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -1,6 +1,9 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.custom.items.CustomBlockItem +import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -124,4 +127,17 @@ object PrePackaged { destination.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) } + + fun itemMatchesRequirement(itemStack: ItemStack, requirement: BlockRequirement): Boolean { + val customBlock = itemStack.customItem as? CustomBlockItem + + if (customBlock != null) { + return requirement.checkBlockData(customBlock.getCustomBlock().blockData) + } + + val type = itemStack.type + if (!type.isBlock) return false + + return requirement.checkBlockData(type.createBlockData()) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 155c864a7c..9b27928321 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -9,12 +9,15 @@ class BlockRequirement( val alias: String, var example: (BlockFace) -> BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, - private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean + private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean, + private val dataCheck: (BlockData) -> Boolean ) { operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) suspend fun checkAsync(block: Block, inward: BlockFace, loadChunks: Boolean) = asyncCheck.invoke(block, inward, loadChunks) + fun checkBlockData(data: BlockData) = dataCheck.invoke(data) + fun setExample(blockData: BlockData): BlockRequirement { this.example = { blockData } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 83d03a8a46..6836574e6f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -36,6 +36,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.isSlab import net.horizonsend.ion.server.miscellaneous.utils.isStainedGlass import net.horizonsend.ion.server.miscellaneous.utils.isStainedGlassPane import net.horizonsend.ion.server.miscellaneous.utils.isStairs +import net.horizonsend.ion.server.miscellaneous.utils.isTerracotta import net.horizonsend.ion.server.miscellaneous.utils.isTrapdoor import net.horizonsend.ion.server.miscellaneous.utils.isWall import net.horizonsend.ion.server.miscellaneous.utils.isWool @@ -48,6 +49,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.Furnace import org.bukkit.block.data.type.Slab +import org.bukkit.block.data.type.Slab.Type.DOUBLE import java.util.EnumSet class MultiblockShape { @@ -267,7 +269,8 @@ class MultiblockShape { alias = type.toString(), example = { type.createBlockData() }, syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, - asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type } + asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type }, + dataCheck = { type == it.material } ) complete(requirement) @@ -286,7 +289,8 @@ class MultiblockShape { val type = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type typeSet.contains(type) - } + }, + dataCheck = { typeSet.contains(it.material) } ) complete(requirement) @@ -305,7 +309,8 @@ class MultiblockShape { }, asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.let { CustomBlocks.getByBlockData(it.data) } === customBlock - } + }, + dataCheck = { CustomBlocks.getByBlockData(it) == customBlock } ) complete(requirement) @@ -355,17 +360,18 @@ class MultiblockShape { example = { Material.STONE_BRICK_SLAB.createBlockData().apply { this as Slab - this.type = Slab.Type.DOUBLE + this.type = DOUBLE } }, syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) - blockData is Slab && blockData.type == Slab.Type.DOUBLE + blockData is Slab && blockData.type == DOUBLE }, asyncCheck = { block, _, loadChunks -> val blockData: BlockData? = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.data - blockData is Slab && blockData.type == Slab.Type.DOUBLE - } + blockData is Slab && blockData.type == DOUBLE + }, + dataCheck = { it is Slab && it.type == DOUBLE } ) ) fun anySlabOrStairs() = filteredTypes("any slab or stairs") { it.isSlab || it.isStairs } @@ -378,15 +384,16 @@ class MultiblockShape { val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) val blockType = if (loadChunks) block.type else block.getTypeSafe() - (blockData is Slab && blockData.type == Slab.Type.DOUBLE) || TERRACOTTA_TYPES.contains(blockType) + (blockData is Slab && blockData.type == DOUBLE) || TERRACOTTA_TYPES.contains(blockType) }, asyncCheck = { block, _, loadChunks -> val blockSnapshot = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks) val blockData = blockSnapshot?.data val blockType = blockSnapshot?.type - (blockData is Slab && blockData.type == Slab.Type.DOUBLE) || TERRACOTTA_TYPES.contains(blockType) - } + (blockData is Slab && blockData.type == DOUBLE) || TERRACOTTA_TYPES.contains(blockType) + }, + dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta } ) } @@ -526,7 +533,8 @@ class MultiblockShape { if (blockData.material != Material.FURNACE) return@asyncCheck false val facing = blockData.facing return@asyncCheck facing == inward.oppositeFace - } + }, + dataCheck = { it is Furnace } )) fun solidBlock() = anyType( From e32383c936fc928133447bd842f044b5cd5b4c95 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 21 Sep 2024 14:26:21 -0500 Subject: [PATCH 190/500] node factory simplification --- .../server/features/multiblock/PrePackaged.kt | 1 + .../features/transport/node/NodeType.kt | 6 +- ...ctionalNode.kt => FluidDirectionalNode.kt} | 2 +- .../{GasValveNode.kt => FluidFilterNode.kt} | 2 +- .../{GasFilterNode.kt => FluidFlowMeter.kt} | 2 +- ...ode.kt => FluidInvertedDirectionalNode.kt} | 2 +- .../node/type/fluid/FluidJunctionNode.kt | 2 +- ...LightningRodNode.kt => FluidLinearNode.kt} | 13 +- .../node/type/fluid/FluidNodeFactory.kt | 77 +-------- .../{GasFlowMeter.kt => FluidValveNode.kt} | 2 +- .../transport/node/type/general/LinearNode.kt | 5 + .../transport/node/type/power/EndRodNode.kt | 7 +- .../node/type/power/PowerEqualSplitterNode.kt | 33 ---- .../node/type/power/PowerNodeFactory.kt | 149 ++++-------------- .../transport/node/type/power/SpongeNode.kt | 5 +- .../transport/node/util/NodeFactory.kt | 49 ++++++ 16 files changed, 111 insertions(+), 246 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/{GasDirectionalNode.kt => FluidDirectionalNode.kt} (71%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/{GasValveNode.kt => FluidFilterNode.kt} (75%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/{GasFilterNode.kt => FluidFlowMeter.kt} (76%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/{GasInvertedDirectionalNode.kt => FluidInvertedDirectionalNode.kt} (66%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/{LightningRodNode.kt => FluidLinearNode.kt} (69%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/{GasFlowMeter.kt => FluidValveNode.kt} (76%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index dced8ef0c8..6caafde197 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -138,6 +138,7 @@ object PrePackaged { val type = itemStack.type if (!type.isBlock) return false + //TODO something with double slabs return requirement.checkBlockData(type.createBlockData()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 77d2b5f708..8dc0406256 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -2,11 +2,10 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.type.fluid.LightningRodNode +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidLinearNode import net.horizonsend.ion.server.features.transport.node.type.power.EndRodNode import net.horizonsend.ion.server.features.transport.node.type.power.InvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerEqualSplitterNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode @@ -23,12 +22,11 @@ enum class NodeType(val clazz: Class) { POWER_FLOW_METER(PowerFlowMeter::class.java), POWER_DIRECTIONAL_NODE(PowerDirectionalNode::class.java), POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), - POWER_EQUAL_SPLITTER(PowerEqualSplitterNode::class.java), //FLUID FLUID_INPUT(net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode::class.java), FLUID_JUNCTION(net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode::class.java), - LIGHTNING_ROD(LightningRodNode::class.java), + LIGHTNING_ROD(FluidLinearNode::class.java), //ITEM ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt similarity index 71% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt index e10a607f71..a0dd0c8a0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class GasDirectionalNode { +class FluidDirectionalNode { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt similarity index 75% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt index 3b5ee9832e..a693762056 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasValveNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class GasValveNode { +class FluidFilterNode { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt similarity index 76% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt index a5b9cbd1a4..c486fa6022 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFilterNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class GasFilterNode { +class FluidFlowMeter { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt similarity index 66% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt index 087b772503..20f6db6b60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasInvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class GasInvertedDirectionalNode { +class FluidInvertedDirectionalNode { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt index 59734e4274..6dcb4d686e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt @@ -12,7 +12,7 @@ class FluidJunctionNode(network: FluidNodeManager) : JunctionNode(position, type, handleRelationships = false) } override fun toString(): String { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/LightningRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/LightningRodNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt index bbccd5b01a..e52b2448b7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/LightningRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.NodeType.LIGHTNING_ROD import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode +import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -11,8 +13,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.Axis import org.bukkit.block.data.Directional -class LightningRodNode(network: FluidNodeManager) : LinearNode(network) { - override val type: NodeType = NodeType.LIGHTNING_ROD +// Aka lightning rod +class FluidLinearNode(network: FluidNodeManager) : LinearNode(network) { + override val type: NodeType = LIGHTNING_ROD constructor(network: FluidNodeManager, origin: Long, axis: Axis) : this(network) { positions.add(origin) @@ -22,10 +25,6 @@ class LightningRodNode(network: FluidNodeManager) : LinearNode(position, data.facing.axis, type, handleRelationships = false) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt index bfa8f73ccb..74ab5efbda 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt @@ -1,14 +1,12 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_INPUT +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_JUNCTION +import net.horizonsend.ion.server.features.transport.node.NodeType.LIGHTNING_ROD import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.power.SpongeNode import net.horizonsend.ion.server.features.transport.node.util.NodeFactory -import net.horizonsend.ion.server.features.transport.node.util.getNeighborNodes -import net.horizonsend.ion.server.features.transport.node.util.handleMerges import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.faces import net.horizonsend.ion.server.miscellaneous.utils.isChiseledCopper import net.horizonsend.ion.server.miscellaneous.utils.isCopperBlock import net.horizonsend.ion.server.miscellaneous.utils.isCopperBulb @@ -21,35 +19,20 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory addLightningRod(data as Directional, key) + data.material == Material.LIGHTNING_ROD -> addLinearNode(key, (data as Directional).facing.axis, LIGHTNING_ROD) + data.material.isCopperBlock -> addJunctionNode(key, FLUID_JUNCTION) - // Omnidirectional wires - data.material.isCopperBlock -> addJunction(key) +// data.material == Material.CRAFTING_TABLE -> addSimpleSingleNode(key, FLUID_EXTRACOTR_NODE) + data.material == Material.FLETCHING_TABLE -> addSimpleSingleNode(key, FLUID_INPUT) - // Extractor - data.material == Material.CRAFTING_TABLE -> println("TODO") - - // Input - data.material == Material.FLETCHING_TABLE -> println("TODO") - - // Flow meter data.material == Material.OBSERVER -> println("TODO") - // Merge data.material == Material.REDSTONE_BLOCK -> println("TODO") data.material == Material.IRON_BLOCK -> println("TODO") +// data.material == Material.LAPIS_BLOCK -> addSimpleSingleNode(key, FLUID_INVERTED_DIRECTIONAL_NODE) - // Inverted Merge - data.material == Material.LAPIS_BLOCK -> println("TODO") - - // Splitter - CustomBlocks.getByBlockData(data) == CustomBlocks.ALUMINUM_BLOCK -> println("TODO") - - // Valve data.material.isChiseledCopper -> println("TODO") - // Filter data.material.isCopperBulb -> println("TODO") else -> return false @@ -57,48 +40,4 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory() - .filterTo(mutableListOf()) { it.axis == axis } - - val finalNode = when (neighbors.size) { - // Disconnected - 0 -> LightningRodNode(network, position, data.facing.axis).apply { loadIntoNetwork() } - - // Consolidate into neighbor - 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") - - // Should be a max of 2 - 2 -> handleMerges(neighbors).addPosition(position) - - else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") - } - - if (handleRelationships) finalNode.rebuildRelations() - } - - fun addJunction(position: BlockKey, handleRelationships: Boolean = true) { - val neighbors = getNeighborNodes(position, network.nodes).values.filterIsInstanceTo>(mutableListOf()) - - val finalNode = when (neighbors.size) { - // New sponge node - 0 -> net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode(network, position).apply { loadIntoNetwork() } - - // Consolidate into neighbor - 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") - - // Join multiple neighbors together - in 2..6 -> handleMerges(neighbors).addPosition(position) - - else -> throw NotImplementedError() - } - - if (handleRelationships) finalNode.rebuildRelations() - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt similarity index 76% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt index 01de9350d1..299ed0401d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/GasFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class GasFlowMeter { +class FluidValveNode { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index 48d47a2f70..6ee42464b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -55,5 +55,10 @@ abstract class LinearNode, B: LinearNode< return new } + fun setAxis(axis: Axis): LinearNode { + this.axis = axis + return this + } + override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationships.size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt index e7de30f217..d3c1d407fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode +import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -22,10 +23,6 @@ class EndRodNode(network: PowerNodeManager) : LinearNode(position, data.facing.axis, type, handleRelationships = false) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt deleted file mode 100644 index 34561c55ff..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerEqualSplitterNode.kt +++ /dev/null @@ -1,33 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -class PowerEqualSplitterNode(override val manager: PowerNodeManager) : SingleNode() { - override val type: NodeType = NodeType.POWER_EQUAL_SPLITTER - constructor(network: PowerNodeManager, position: BlockKey) : this(network) { - this.position = position - } - - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is PowerExtractorNode && node !is SolarPanelNode - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt index b046b3c28e..580e708612 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt @@ -1,18 +1,18 @@ package net.horizonsend.ion.server.features.transport.node.type.power -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_EXTRACTOR_NODE +import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_INPUT_NODE +import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_INVERSE_DIRECTIONAL_NODE import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode.Companion.matchesSolarPanelStructure import net.horizonsend.ion.server.features.transport.node.util.NodeFactory -import net.horizonsend.ion.server.features.transport.node.util.getNeighborNodes import net.horizonsend.ion.server.features.transport.node.util.handleMerges import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Material -import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.BlockFace.UP import org.bukkit.block.data.BlockData @@ -22,123 +22,31 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory addEndRod(data as Directional, key) + when (data.material) { + Material.END_ROD -> addLinearNode(key, (data as Directional).facing.axis, NodeType.END_ROD_NODE) + Material.SPONGE -> addJunctionNode(key, NodeType.SPONGE_NODE) - // Omnidirectional wires - data.material == Material.SPONGE -> addSponge(key) + // If a solar panel is not created, add an extractor + Material.CRAFTING_TABLE -> if (!checkSolarPanels(key, 1)) addSimpleSingleNode(key, POWER_EXTRACTOR_NODE) + Material.DIAMOND_BLOCK -> checkSolarPanels(key, 1) + Material.DAYLIGHT_DETECTOR -> checkSolarPanels(key, 2) - // Extract power from storage - data.material == Material.CRAFTING_TABLE -> { - if (matchesSolarPanelStructure(network.world, key)) { - addSolarPanel(key) - } else { - addExtractor(key) - } - } - - // Check for extractor beneath - data.material == Material.DIAMOND_BLOCK -> { - val extractorKey = getRelative(key, DOWN, 1) - - if (matchesSolarPanelStructure(network.world, extractorKey)) { - network.nodes.remove(extractorKey) - addSolarPanel(extractorKey) - } - } - - data.material == Material.DAYLIGHT_DETECTOR -> { - val extractorKey = getRelative(key, DOWN, 2) + Material.NOTE_BLOCK -> addSimpleSingleNode(key, POWER_INPUT_NODE) + Material.OBSERVER -> addFlowMeter(data as Directional, key) - if (matchesSolarPanelStructure(network.world, extractorKey)) { - network.nodes.remove(extractorKey) - addSolarPanel(extractorKey) - } - } - - // Add power to storage - data.material == Material.NOTE_BLOCK -> addInput(key) - - // Power flow meter - data.material == Material.OBSERVER -> addFlowMeter(data as Directional, key) - - // Merge node behavior - data.material == Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) - data.material == Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) - - // Split power evenly - CustomBlocks.getByBlockData(data) == CustomBlocks.ALUMINUM_BLOCK -> addEqualSplitterNode(key) + Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) + Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) + Material.LAPIS_BLOCK -> addSimpleSingleNode(key, POWER_INVERSE_DIRECTIONAL_NODE) // Redstone controlled gate -// block.type.isRedstoneLamp -> GateNode(this, x, y, z) - + // block.type.isRedstoneLamp -> GateNode(this, x, y, z) else -> return false } return true } - fun addSponge(position: BlockKey, handleRelationships: Boolean = true) { - val neighbors = getNeighborNodes(position, network.nodes).values.filterIsInstanceTo>(mutableListOf()) - - val finalNode = when (neighbors.size) { - // New sponge node - 0 -> SpongeNode(network, position).addPosition(position) - - // Consolidate into neighbor - 1 -> { - val adjacent = neighbors.firstOrNull() - adjacent?.addPosition(position) ?: SpongeNode(network, position).apply { loadIntoNetwork() } - } - - // Join multiple neighbors together - in 2..6 -> handleMerges(neighbors).addPosition(position) - - else -> throw NotImplementedError() - } - - if (handleRelationships) finalNode.rebuildRelations() - } - - fun addEndRod(data: Directional, position: Long, handleRelationships: Boolean = true) { - val axis = data.facing.axis - - // The neighbors in the direction of the wire's facing, that are also facing that direction - val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()) - .values - .filterIsInstance() - .filterTo(mutableListOf()) { it.axis == axis } - - val finalNode = when (neighbors.size) { - // Disconnected - 0 -> EndRodNode(network, position, data.facing.axis).addPosition(position) - - // Consolidate into neighbor - 1 -> neighbors.firstOrNull()?.addPosition(position) ?: throw ConcurrentModificationException("Node removed during processing") - - // Should be a max of 2 - 2 -> handleMerges(neighbors).addPosition(position) - - else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") - } - - if (handleRelationships) finalNode.rebuildRelations() - } - - fun addExtractor(position: BlockKey) { - network.nodes[position] = PowerExtractorNode(network, position).apply { - onPlace(position) - } - } - - fun addInput(position: BlockKey) { - network.nodes[position] = PowerInputNode(network, position).apply { - onPlace(position) - } - } - - fun addFlowMeter(data: Directional, position: BlockKey) { + private fun addFlowMeter(data: Directional, position: BlockKey) { network.nodes[position] = PowerFlowMeter(network, position, data.facing).apply { onPlace(position) } @@ -166,7 +74,7 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory(network) { - override val type: NodeType = NodeType.SPONGE_NODE + override val type: NodeType = SPONGE_NODE constructor(network: PowerNodeManager, origin: BlockKey) : this(network) { positions.add(origin) } override fun addBack(position: BlockKey) { - manager.nodeFactory.addSponge(position, handleRelationships = false) + manager.nodeFactory.addJunctionNode(position, type, handleRelationships = false) } override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes) location = ${toVec3i(positions.random())}" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt index 030f8198cd..f23c36497c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt @@ -1,7 +1,14 @@ package net.horizonsend.ion.server.features.transport.node.util +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode +import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.faces +import org.bukkit.Axis import org.bukkit.block.data.BlockData abstract class NodeFactory(val network: T) { @@ -9,4 +16,46 @@ abstract class NodeFactory(val network: T) { * Create and handle placement of a node at the position, if one should be created **/ abstract fun create(key: BlockKey, data: BlockData): Boolean + + inline fun > addJunctionNode(position: BlockKey, type: NodeType, handleRelationships: Boolean = true) { + val neighbors = getNeighborNodes(position, network.nodes).values.filterIsInstanceTo>(mutableListOf()) + + val finalNode = when (neighbors.size) { + 0 -> newNode(type).addPosition(position) // New sponge node + 1 -> neighbors.firstOrNull()?.addPosition(position) ?: newNode(type).addPosition(position) // Consolidate into neighbor + in 2..6 -> handleMerges(neighbors).addPosition(position) // Join multiple neighbors together + + else -> throw NotImplementedError() + } + if (handleRelationships) finalNode.rebuildRelations() + } + + inline fun > addLinearNode(position: BlockKey, axis: Axis, type: NodeType, handleRelationships: Boolean = true) { + // The neighbors in the direction of the wire's facing, that are also facing that direction + val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()) + .values + .filterIsInstance() + .filterTo(mutableListOf()) { it.axis == axis && it.type == type } + + val finalNode = when (neighbors.size) { + 0 -> newNode(type).addPosition(position).setAxis(axis) + 1 -> neighbors.firstOrNull()?.addPosition(position) ?: newNode(type).addPosition(position).setAxis(axis) + 2 -> handleMerges(neighbors).addPosition(position) + + else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") + } + + if (handleRelationships) finalNode.rebuildRelations() + } + + fun addSimpleSingleNode(position: BlockKey, type: NodeType) { + val new = type.newInstance(network) as SingleNode + + new.position = position + new.onPlace(position) + + network.nodes[position] = new + } + + inline fun newNode(type: NodeType): T = type.newInstance(network) as T } From 6a8f925beb8712e69a7e226bf9d6154068d09212 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 21 Sep 2024 14:35:11 -0500 Subject: [PATCH 191/500] fix liner node splitting --- .../transport/node/type/fluid/FluidLinearNode.kt | 6 ------ .../transport/node/type/general/LinearNode.kt | 15 ++++++++++++--- .../transport/node/type/power/EndRodNode.kt | 6 ------ 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt index e52b2448b7..c2b3153202 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt @@ -10,18 +10,12 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import org.bukkit.Axis import org.bukkit.block.data.Directional // Aka lightning rod class FluidLinearNode(network: FluidNodeManager) : LinearNode(network) { override val type: NodeType = LIGHTNING_ROD - constructor(network: FluidNodeManager, origin: Long, axis: Axis) : this(network) { - positions.add(origin) - this.axis = axis - } - override fun addBack(position: BlockKey) { val data = getBlockDataSafe(manager.world, getX(position), getY(position), getZ(position)) as? Directional ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index 6ee42464b6..3cde852119 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -50,9 +50,18 @@ abstract class LinearNode, B: LinearNode< } override fun ofPositions(positions: Set): B { - val new = super.ofPositions(positions) - new.axis = axis - return new + @Suppress("UNCHECKED_CAST") + val newNode = type.newInstance(manager) as B + + // Need to set the axis before the rebuild, hence the override + newNode.axis = axis + + positions.forEach { + newNode.addPosition(it) + newNode.buildRelations(it) + } + + return newNode } fun setAxis(axis: Axis): LinearNode { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt index d3c1d407fa..8fce3c5bb7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt @@ -9,17 +9,11 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import org.bukkit.Axis import org.bukkit.block.data.Directional class EndRodNode(network: PowerNodeManager) : LinearNode(network) { override val type: NodeType = NodeType.END_ROD_NODE - constructor(network: PowerNodeManager, origin: Long, axis: Axis) : this(network) { - positions.add(origin) - this.axis = axis - } - override fun addBack(position: BlockKey) { val data = getBlockDataSafe(manager.world, getX(position), getY(position), getZ(position)) as? Directional ?: return From 582d26c5b7b2638290551771bdd6333757a1b968 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 22 Sep 2024 13:53:30 -0500 Subject: [PATCH 192/500] multimeter --- .../custom/items/misc/MultimeterItem.kt | 102 ++++++++++++++++++ .../node/manager/FluidNodeManager.kt | 4 +- .../features/transport/node/util/NodeUtils.kt | 13 ++- .../persistence/NamespacedKeys.kt | 2 +- 4 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt new file mode 100644 index 0000000000..c139cf5195 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -0,0 +1,102 @@ +package net.horizonsend.ion.server.features.custom.items.misc + +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.success +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.node.util.getIdealPath +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_VARIANT +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.audience.Audience +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.TextDecoration +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataType.INTEGER +import org.bukkit.persistence.PersistentDataType.LONG + +object MultimeterItem : CustomItem("Multimeter") { + override fun constructItemStack(): ItemStack { + return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + it.displayName(Component.text("Multimeter", NamedTextColor.YELLOW).decoration(TextDecoration.ITALIC, false)) + it.persistentDataContainer.set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, identifier) + } + } + + override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + val targeted = livingEntity.getTargetBlock(null, 10) + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + itemStack.updateMeta { + it.persistentDataContainer.set(X, LONG, key) + } + + livingEntity.information("Set first point to ${toVec3i(key)}") + + tryCheckResistance(livingEntity, livingEntity.world, itemStack) + } + + override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + if (livingEntity !is Player) return + if (livingEntity.isSneaking) { + cycleNetworks(livingEntity, livingEntity.world, itemStack) + return + } + + val targeted = livingEntity.getTargetBlock(null, 10) + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + itemStack.updateMeta { + it.persistentDataContainer.set(Z, LONG, key) + } + + livingEntity.information("Set second point to ${toVec3i(key)}") + + tryCheckResistance(livingEntity, livingEntity.world, itemStack) + } + + private fun tryCheckResistance(audience: Audience, world: World, itemStack: ItemStack) { + val firstPoint = itemStack.itemMeta.persistentDataContainer.get(X, LONG) ?: return + val firstChunk = IonChunk[world, getX(firstPoint).shr(4), getZ(firstPoint).shr(4)] ?: return + val secondPoint = itemStack.itemMeta.persistentDataContainer.get(Z, LONG) ?: return + val secondChunk = IonChunk[world, getX(secondPoint).shr(4), getZ(secondPoint).shr(4)] ?: return + + val networkTypeIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) + val networkType = NetworkType.entries[networkTypeIndex] + + val firstNode = networkType.get(firstChunk).getNode(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") + val secondNode = networkType.get(secondChunk).getNode(secondPoint) ?: return audience.information("There is no node at ${toVec3i(secondPoint)}") + + val path = getIdealPath(firstNode, secondNode) + val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") + audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${secondNode.javaClass.simpleName} at ${toVec3i(secondPoint)} is $resistance") + } + + private fun cycleNetworks(audience: Audience, world: World, itemStack: ItemStack) { + val currentIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) + val newIndex = (currentIndex + 1) % NetworkType.entries.size + itemStack.updateMeta { + it.persistentDataContainer.set(NODE_VARIANT, INTEGER, newIndex) + } + + audience.success("Set network type to ${NetworkType.entries[newIndex]}") + + tryCheckResistance(audience, world, itemStack) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index a245daccfb..62ea330def 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -3,13 +3,13 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidNodeFactory import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.GAS_TRANSPORT +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_TRANSPORT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { - override val namespacedKey: NamespacedKey = GAS_TRANSPORT + override val namespacedKey: NamespacedKey = FLUID_TRANSPORT override val type: NetworkType = NetworkType.FLUID override val nodeFactory = FluidNodeFactory(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt index 586912d07e..8b442276e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -13,6 +14,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull +import org.bukkit.NamespacedKey import org.bukkit.block.BlockFace import java.util.LinkedList @@ -108,8 +110,8 @@ fun > separateNodePositions(node: T): List> { } -enum class NetworkType { - POWER { +enum class NetworkType(val namespacedKey: NamespacedKey) { + POWER(NamespacedKeys.POWER_TRANSPORT) { override fun get(chunk: IonChunk): NodeManager { return chunk.transportNetwork.powerNodeManager.network } @@ -118,7 +120,7 @@ enum class NetworkType { TODO("Not yet implemented") } }, - FLUID { + FLUID(NamespacedKeys.FLUID_TRANSPORT) { override fun get(chunk: IonChunk): NodeManager { return chunk.transportNetwork.powerNodeManager.network } @@ -133,4 +135,9 @@ enum class NetworkType { abstract fun get(chunk: IonChunk): NodeManager abstract fun get(ship: ActiveStarship): NodeManager + + companion object { + private val byKey = entries.associateBy { it.namespacedKey } + operator fun get(key: NamespacedKey): NetworkType = byKey[key]!! + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index b132a7b69f..3e65d7c714 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -59,7 +59,7 @@ object NamespacedKeys { val GAS = key("Gas") val POWER_TRANSPORT = key("power_transport") - val GAS_TRANSPORT = key("gas_transport") + val FLUID_TRANSPORT = key("gas_transport") val ITEM_TRANSPORT = key("item_transport") val TUBE_BUTTONS = key("tube_buttons") From ac5a6435a2a663047a562870d5225ea91c0fe334 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 22 Sep 2024 14:28:17 -0500 Subject: [PATCH 193/500] fix resistance bug --- .../features/transport/node/type/general/JunctionNode.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt index bb57d6d5a2..690d4c58d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt @@ -34,7 +34,7 @@ abstract class JunctionNode, B: Junctio if (nextNode != null) { // Provided both means it needs to be more precise for an accurate distribution of resources. Get in / out locations via relations val relationPrevious = getRelationshipWith(previousNode) - val relationNext = getRelationshipWith(previousNode) + val relationNext = getRelationshipWith(nextNode) val previousVec = Vec3i( relationPrevious.keys.averageBy { getX(it).toDouble() }.roundToInt(), @@ -48,7 +48,7 @@ abstract class JunctionNode, B: Junctio relationNext.keys.averageBy { getZ(it).toDouble() }.roundToInt() ) - return previousVec.distance(nextVec).roundToInt() + return maxOf(1, previousVec.distance(nextVec).roundToInt()) } // Rough distance From e4ab4953b48a47d4e5147df08974dec6aaf6f06a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 22 Sep 2024 16:19:22 -0500 Subject: [PATCH 194/500] finished power transfer --- .../node/manager/PowerNodeManager.kt | 140 +++++++++++------- .../node/type/power/PowerExtractorNode.kt | 2 + .../node/type/power/PowerInputNode.kt | 30 ++++ 3 files changed, 117 insertions(+), 55 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 8be50f04ee..1bc69e0983 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.node.manager import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder @@ -54,86 +53,117 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { - val powerCheck = solarPanelNode.getPower() + val powerCheck = solarPanelNode.tickAndGetPower() if (powerCheck == 0) return@submit val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) - runPowerTransfer(solarPanelNode, destinations.toList(), solarPanelNode.tickAndGetPower()) + runPowerTransfer(solarPanelNode, destinations.toList(), powerCheck) } +} - private fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } +// These methods are outside the class for speed - /** - * Runs the power transfer from the source to the destinations. pending rewrite - **/ - private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { - if (destinations.isEmpty()) return availableTransferPower - val numDestinations = destinations.size +private fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } - var maximumResistance: Double = -1.0 +/** + * Runs the power transfer from the source to the destinations. pending rewrite + **/ +private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { + if (destinations.isEmpty()) return availableTransferPower + val numDestinations = destinations.size - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, destinations[it]) - }.getOrNull() } + var maximumResistance: Double = -1.0 - // Perform the calc & max find in the same loop - val pathResistance: Array = Array(numDestinations) { - val res = calculatePathResistance(paths[it]) - if (res != null && maximumResistance < res) maximumResistance = res + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(source, destinations[it]) + }.getOrNull() } - res - } + // Perform the calc & max find in the same loop + val pathResistance: Array = Array(numDestinations) { + val res = calculatePathResistance(paths[it]) + if (res != null && maximumResistance < res) maximumResistance = res - // All null, no paths found - if (maximumResistance == -1.0) return availableTransferPower + res + } - var shareFactorSum = 0.0 + // All null, no paths found + if (maximumResistance == -1.0) return availableTransferPower - val shareFactors: Array = Array(numDestinations) { index -> - val resistance = pathResistance[index] ?: return@Array null - val fac = (numDestinations - index).toDouble() / (resistance / maximumResistance) - shareFactorSum += fac + var shareFactorSum = 0.0 - fac - } + // Get a parallel array containing the ascending order of resistances + val sortedIndexes = getSorted(pathResistance) - var remainingPower = availableTransferPower + val shareFactors: Array = Array(numDestinations) { index -> + val resistance = pathResistance[index] ?: return@Array null + val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) + shareFactorSum += fac - // Just cast once - val powerSource = source as? PowerExtractorNode + fac + } - for ((index, destination) in destinations.withIndex()) { - val shareFactor = shareFactors[index] ?: continue - val share = shareFactor / shareFactorSum + var remainingPower = availableTransferPower - val recipient = destination.getPoweredEntities().randomOrNull() ?: continue + // Just cast once + val powerSource = (source as? PowerExtractorNode) - val idealSend = (availableTransferPower * share).roundToInt() - val toSend = minOf(idealSend, recipient.storage.getRemainingCapacity()) - val couldNotRemove = powerSource?.drawPower(toSend) ?: 0 // If null, source is a solar panel, and can't be removed from. + for ((index, destination) in destinations.withIndex()) { + val shareFactor = shareFactors[index] ?: continue + val share = shareFactor / shareFactorSum - val realAdd = toSend - couldNotRemove + val idealSend = (availableTransferPower * share).roundToInt() + val toSend = minOf(idealSend, getRemainingCapacity(destination)) + val couldNotRemove = powerSource?.drawPower(toSend) ?: 0 // If null, source is a solar panel, and can't be removed from. - val remainder = recipient.storage.addPower(realAdd) - val realTaken = realAdd - remainder + // Following the power distribution + val realAdd = toSend - couldNotRemove - remainingPower -= realTaken - paths[index]?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(realTaken) } + // Amount of power that didn't fit + val remainder = destination.distributePower(realAdd) + val realTaken = realAdd - remainder - // All sent - if (remainder == 0) continue + remainingPower -= realTaken + completeChain(paths[index], realTaken) - // Get the proportion of the amount of power that sent compared to the ideal calculations. - val usedShare = realTaken.toDouble() / idealSend.toDouble() - // Use that to get a proportion of the share factor, and remove that from the sum. - val toRemove = shareFactor * usedShare - shareFactorSum -= toRemove - } + if (remainder == 0) continue - return remainingPower + // Get the proportion of the amount of power that sent compared to the ideal calculations. + val usedShare = realTaken.toDouble() / idealSend.toDouble() + // Use that to get a proportion of the share factor, and remove that from the sum. + val toRemove = shareFactor * usedShare + shareFactorSum -= toRemove } - fun addPower(recipients: Collection): Int { - TODO("") + return remainingPower +} + +private fun getRemainingCapacity(destination: PowerInputNode): Int { + return destination.getPoweredEntities().sumOf { it.storage.getRemainingCapacity() } +} + +private fun completeChain(path: Array?, transferred: Int) { + path?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(transferred) } +} + +// I hate this function but it works +fun getSorted(pathResistance: Array): IntArray { + // Store the shuffled indicies + val ranks = IntArray(pathResistance.size) { it } + val tempSorted = pathResistance.clone() + + for (index in ranks.indices) { + for (j in 0..< ranks.lastIndex) { + if ((tempSorted[j] ?: Double.MAX_VALUE) > (tempSorted[j + 1] ?: Double.MAX_VALUE)) { + val temp = tempSorted[j] + tempSorted[j] = tempSorted[j + 1] + tempSorted[j + 1] = temp + + val prev = ranks[j] + ranks[j] = prev + 1 + ranks[j + 1] = prev + } + } } + + return ranks } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 9d3039376f..0104c95075 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -96,6 +96,8 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() return 0 } + fun getSourcePool() = relationships.mapNotNull { it.value.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } + override fun toString(): String { return "Extractor. found, can trasnsfer: ${getTransferPower()}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt index c57de5c2f2..d48a79b559 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt @@ -58,6 +58,36 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { } } + fun distributePower(power: Int): Int { + val entities = getPoweredEntities().filterTo(mutableListOf()) { !it.storage.isFull() } + if (entities.isEmpty()) return power + + // Skip math for most scenarios + if (entities.size == 1) { return entities.first().storage.addPower(power) } + + var remainingPower = power + + while (remainingPower > 0) { + if (entities.isEmpty()) break + + val share = remainingPower / entities.size + val minRemaining = entities.minOf { it.storage.getRemainingCapacity() } + val distributed = minOf(minRemaining, share) + + val iterator = entities.iterator() + while (iterator.hasNext()) { + val entity = iterator.next() + + val r = entity.storage.addPower(distributed) + if (entity.storage.isFull()) iterator.remove() + + remainingPower -= (distributed - r) + } + } + + return remainingPower + } + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 0 } From 4655865e40df8c7d245a5178e684d9c47f6534f9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 22 Sep 2024 16:43:09 -0500 Subject: [PATCH 195/500] migrate signs when pasting --- .../features/multiblock/MultiblockEntities.kt | 21 ++++++++++++++++--- .../entity/type/LegacyMultiblockEntity.kt | 4 +--- .../multiblock/manager/MultiblockManager.kt | 6 ++++-- .../type/power/storage/PowerBankMultiblock.kt | 18 +++++++++++++++- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 6ea8f55844..62e96405c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock import com.destroystokyo.paper.event.server.ServerTickEndEvent import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -83,10 +84,12 @@ object MultiblockEntities : SLEventListener() { } fun loadFromSign(sign: Sign) { - val data = sign.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return - val origin = MultiblockEntity.getOriginFromSign(sign) val multiblockType = MultiblockAccess.getFast(sign) as? EntityMultiblock<*> ?: return + val data = sign.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return migrateFromSign(sign, multiblockType) + + val origin = MultiblockEntity.getOriginFromSign(sign) + // In case it moved data.x = origin.x data.y = origin.y @@ -94,10 +97,22 @@ object MultiblockEntities : SLEventListener() { data.signOffset = sign.getFacing().oppositeFace setMultiblockEntity(sign.world, origin.x, origin.y, origin.z) { manager -> - loadFromData(multiblockType, manager, data) + val new = loadFromData(multiblockType, manager, data) + if (new is LegacyMultiblockEntity) new.loadFromSign(sign) + + new } } + private fun migrateFromSign(sign: Sign, type: EntityMultiblock<*>) { + val origin = MultiblockEntity.getOriginFromSign(sign) + + val ionChunk = getIonChunk(sign.world, origin.x, origin.z) ?: return + val new = ionChunk.multiblockManager.handleNewMultiblockEntity(type, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) + + if (new is LegacyMultiblockEntity) new.loadFromSign(sign) + } + @EventHandler fun onTickEnd(event: ServerTickEndEvent) { if (event.timeRemaining < 0) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt index 9d1c6267f7..483ab35e74 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt @@ -3,7 +3,5 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import org.bukkit.block.Sign interface LegacyMultiblockEntity { - fun loadFromSign(sign: Sign) { - - } + fun loadFromSign(sign: Sign) {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 060292ebb0..1937aa1a6c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -77,13 +77,13 @@ abstract class MultiblockManager(val log: Logger) { /** * Add a new multiblock to the chunk data **/ - fun handleNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace) { + fun handleNewMultiblockEntity(multiblock: EntityMultiblock<*>, x: Int, y: Int, z: Int, face: BlockFace): MultiblockEntity? { multiblock as Multiblock // Abort process if one already exists, so it's not overwritten if (isOccupied(x, y, z)) { log.warn("Attempted to place a multiblock where one already existed!") - return + return null } // Create new empty data @@ -97,6 +97,8 @@ abstract class MultiblockManager(val log: Logger) { // Place the entity into the chunk addMultiblockEntity(entity) + + return entity } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 60da798a72..96e5152168 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -5,17 +5,23 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.front +import net.kyori.adventure.text.Component.empty import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { abstract val tierMaterial: Material @@ -110,7 +116,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM z: Int, world: World, structureDirection: BlockFace - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = newMultiblockSignOverlay( @@ -139,5 +145,15 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM } override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) + + override fun loadFromSign(sign: Sign) { + val oldPower = sign.persistentDataContainer.get(NamespacedKeys.POWER, PersistentDataType.INTEGER) ?: return + + storage.setPower(oldPower) + + sign.persistentDataContainer.remove(NamespacedKeys.POWER) + sign.front().line(2, empty()) + sign.update() + } } } From 9d8962b9690b7ae77a48b05981ce25798ee8644f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 22 Sep 2024 16:51:13 -0500 Subject: [PATCH 196/500] save to sign when placing --- .../ion/server/features/multiblock/MultiblockEntities.kt | 1 + .../ion/server/features/multiblock/manager/MultiblockManager.kt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 62e96405c4..35a6ac0b59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -111,6 +111,7 @@ object MultiblockEntities : SLEventListener() { val new = ionChunk.multiblockManager.handleNewMultiblockEntity(type, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) if (new is LegacyMultiblockEntity) new.loadFromSign(sign) + new?.saveToSign() } @EventHandler diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 1937aa1a6c..1048c92a60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -98,6 +98,8 @@ abstract class MultiblockManager(val log: Logger) { // Place the entity into the chunk addMultiblockEntity(entity) + entity.saveToSign() + return entity } From 86076bea69da8ccb40840e0dd561372b0a4970db Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 22 Sep 2024 23:30:33 -0500 Subject: [PATCH 197/500] implement directional nodes --- .../transport/node/type/power/EndRodNode.kt | 5 +++- .../type/power/InvertedDirectionalNode.kt | 22 +++++++++++++----- .../node/type/power/PowerDirectionalNode.kt | 23 ++++++++++++++++++- .../node/type/power/PowerExtractorNode.kt | 4 +++- .../node/type/power/PowerFlowMeter.kt | 6 +++-- .../node/type/power/PowerInputNode.kt | 18 +++++++-------- .../node/type/power/PowerPathfindingNode.kt | 10 ++++++++ .../node/type/power/SolarPanelNode.kt | 6 ++--- .../transport/node/type/power/SpongeNode.kt | 9 ++++---- .../transport/node/util/NodePathfinding.kt | 11 +++++---- .../server/features/world/data/DataFixers.kt | 5 +--- 11 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt index 8fce3c5bb7..1ff1dcd87e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode import net.horizonsend.ion.server.miscellaneous.utils.axis @@ -11,7 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.block.data.Directional -class EndRodNode(network: PowerNodeManager) : LinearNode(network) { +class EndRodNode(network: PowerNodeManager) : LinearNode(network), PowerPathfindingNode { override val type: NodeType = NodeType.END_ROD_NODE override fun addBack(position: BlockKey) { @@ -19,4 +20,6 @@ class EndRodNode(network: PowerNodeManager) : LinearNode(position, data.facing.axis, type, handleRelationships = false) } + + override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt index 148ce927fd..6083c91cc0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt @@ -5,17 +5,13 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode() { +class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_INVERSE_DIRECTIONAL_NODE - constructor(network: PowerNodeManager, position: BlockKey) : this(network) { - this.position = position - } - override fun isTransferableTo(node: TransportNode): Boolean { if (node is EndRodNode) return false return node !is PowerExtractorNode && node !is SolarPanelNode @@ -32,4 +28,18 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 1 } + + override fun getNextNodes(previous: TransportNode): ArrayDeque { + // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. + // So there will likely only be a single relation to this + val direction = previous.getRelationshipWith(this).values + if (direction.isEmpty()) return cachedTransferable // just in case + val face = direction.first().offset + + getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } + + return cachedTransferable + } + + fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationships.values.firstOrNull { it.offset == incoming.oppositeFace && it.canTransfer }?.other } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index 7bf2fb85b6..40b650578a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -6,13 +6,15 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode() { +class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_DIRECTIONAL_NODE private var variant: Material by Delegates.notNull() @@ -43,4 +45,23 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 1 } + + override fun getNextNodes(previous: TransportNode): ArrayDeque { + // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. + // So there will likely only be a single relation to this + val direction = previous.getRelationshipWith(this).values + if (direction.isEmpty()) return cachedTransferable + val face = direction.first().offset + + getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } + + return cachedTransferable + } + + fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationships.values.firstOrNull { it.offset == incoming.oppositeFace && it.canTransfer }?.other + + override fun toString(): String { + val face = ADJACENT_BLOCK_FACES.random() + return "directional: $face is ${getForwardTransferable(face)}, $cachedTransferable" + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 0104c95075..e4a2b2fdbf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -11,7 +11,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt -class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() { +class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE constructor(network: PowerNodeManager, position: BlockKey) : this(network) { @@ -101,5 +101,7 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode() override fun toString(): String { return "Extractor. found, can trasnsfer: ${getTransferPower()}" } + + override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt index 3b9c8d017a..df6f570591 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt @@ -24,7 +24,7 @@ import org.bukkit.block.BlockFace.NORTH import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { +class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_FLOW_METER constructor(network: PowerNodeManager, position: BlockKey, direction: BlockFace) : this(network) { this.position = position @@ -108,7 +108,7 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { } override fun onPlace(position: BlockKey) { - setupDisplayEntity() + runCatching { setupDisplayEntity() } super.onPlace(position) } @@ -134,4 +134,6 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode() { override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 1 } + + override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt index d48a79b559..b933d6eeef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManag import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -19,15 +18,8 @@ import org.bukkit.block.data.type.WallSign import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { +class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_INPUT_NODE - constructor(network: PowerNodeManager, position: BlockKey) : this(network) { - this.position = position - } - - override fun isTransferableTo(node: TransportNode): Boolean { - return false - } override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) @@ -92,5 +84,13 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode() { return 0 } + override fun getNextNodes(previous: TransportNode): ArrayDeque { + return ArrayDeque(0) // Can't transfer to anything + } + + override fun isTransferableTo(node: TransportNode): Boolean { + return false + } + override fun toString(): String = "POWER INPUT NODE. Bound to ${getPoweredEntities().joinToString { it.toString() }}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt new file mode 100644 index 0000000000..714699cd65 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.node.type.power + +import net.horizonsend.ion.server.features.transport.node.TransportNode + +interface PowerPathfindingNode { + /** + * For use in pathfinding. When entering from previous node, get the list of available next nodes. Mostly used by the flood fill. + **/ + fun getNextNodes(previous: TransportNode): ArrayDeque +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt index 658e350665..3a5af1e608 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt @@ -30,9 +30,7 @@ import java.util.function.Consumer /** * Represents a solar panel, or multiple **/ -class SolarPanelNode( - override val manager: PowerNodeManager -) : MultiNode() { +class SolarPanelNode(override val manager: PowerNodeManager) : MultiNode(), PowerPathfindingNode { override val type: NodeType = NodeType.SOLAR_PANEL_NODE /** The positions of extractors in this solar panel */ private val extractorPositions = ConcurrentHashMap.newKeySet() @@ -264,6 +262,8 @@ class SolarPanelNode( } } + override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable + override fun toString(): String = "(SOLAR PANEL NODE:" + " Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, " + "distance = $exitDistance," + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt index e93abc6d53..c44b0b48da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.NodeType.SPONGE_NODE +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -12,16 +13,14 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i * * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly **/ -class SpongeNode(network: PowerNodeManager) : JunctionNode(network) { +class SpongeNode(network: PowerNodeManager) : JunctionNode(network), PowerPathfindingNode { override val type: NodeType = SPONGE_NODE - constructor(network: PowerNodeManager, origin: BlockKey) : this(network) { - positions.add(origin) - } - override fun addBack(position: BlockKey) { manager.nodeFactory.addJunctionNode(position, type, handleRelationships = false) } + override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable + override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes) location = ${toVec3i(positions.random())}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index 63d5d24b3a..d2b3b6f7b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.util import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode import kotlin.math.roundToInt inline fun getNetworkDestinations(origin: TransportNode, check: (T) -> Boolean): ObjectOpenHashSet { @@ -40,9 +41,7 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? iterations++ val current = queue.minBy { it.f } - if (current.node == to) { - return current.buildPath() - } + if (current.node == to) return current.buildPath() queue.remove(current) visited.add(current) @@ -68,7 +67,11 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution private fun getNeighbors(parent: PathfindingNodeWrapper): Array { - val transferable = parent.node.cachedTransferable + val parentParent = parent.parent + val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { + parent.node.getNextNodes(parentParent.node) + } else parent.node.cachedTransferable + return Array(transferable.size) { val neighbor = transferable[it] diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt index 72138d7677..d9ca42259a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/DataFixers.kt @@ -53,13 +53,10 @@ object DataFixers: IonServerComponent() { chunk.dataVersion = chunkDataFixer.dataVersion } + return SignFixerEntrance.iterateChunk(chunk) } - fun handleMultiblockEntityLoad() { - //TODO - } - fun handleMultiblockSignLoad(sign: Sign) { val dataVersion = sign.persistentDataContainer.getOrDefault(DATA_VERSION, INTEGER, 0) From 20d9992d8ca2502ed24330e301cdbc273bd774bc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 24 Sep 2024 01:22:39 -0500 Subject: [PATCH 198/500] even more performance improvements --- .../client/display/modular/display/Display.kt | 2 ++ .../modular/display/PowerEntityDisplay.kt | 4 +-- .../entity/type/power/PowerStorage.kt | 4 --- .../server/features/transport/NewTransport.kt | 2 +- .../features/transport/node/TransportNode.kt | 5 ++- .../node/manager/PowerNodeManager.kt | 15 ++++++--- .../transport/node/type/general/LinearNode.kt | 11 +++++++ .../type/power/InvertedDirectionalNode.kt | 4 ++- .../node/type/power/PowerExtractorNode.kt | 28 ++++++++++++---- .../transport/node/util/NodePathfinding.kt | 33 ++++++++++++++----- 10 files changed, 81 insertions(+), 27 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index c14a9dcdc3..04db94ea37 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -123,6 +123,8 @@ abstract class Display( update() } + private val distSquared = (50.0 * 50.0) + fun update() { setText(getText()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt index 0b74ad86ab..1dbe1c2145 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt @@ -22,11 +22,11 @@ class PowerEntityDisplay( } override fun register() { - multiblockEntity.storage.registerUpdateHandler(updateHandler) +// multiblockEntity.storage.registerUpdateHandler(updateHandler) } override fun deRegister() { - multiblockEntity.storage.removeUpdateHandler(updateHandler) +// multiblockEntity.storage.removeUpdateHandler(updateHandler) } override fun getText(): Component { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index 2b3659c8fc..91e32f4cb8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import java.util.concurrent.ConcurrentHashMap class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacity: Int) { @@ -18,7 +17,6 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit backingPower = correctedPower } - (holder as MultiblockEntity).markChanged() runUpdates() } @@ -38,7 +36,6 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit newAmount } - (holder as MultiblockEntity).markChanged() runUpdates() return if (newAmount > capacity) capacity - newAmount else 0 @@ -56,7 +53,6 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit newAmount } - (holder as MultiblockEntity).markChanged() runUpdates() return if (newAmount < 0) newAmount else 0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index ce0f6d51f8..e6c30d334b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -10,7 +10,7 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import kotlin.concurrent.fixedRateTimer -object NewTransport : IonServerComponent() { +object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick to wait on the full server startup. */) { private val transportManagers = ConcurrentHashMap.newKeySet() lateinit var monitorThread: Timer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index fc94a640d2..f9336710a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -78,6 +78,7 @@ abstract class TransportNode : PDCSerializable>() + fun getRelationshipWith(other: TransportNode): Map { - return relationships.filter { it.value.other == other } + return relationCache.getOrPut(other) { relationships.filter { it.value.other == other } } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 1bc69e0983..1143a3136d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -48,7 +48,12 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) val transferred = extractorNode.getTransferPower() - runPowerTransfer(extractorNode, destinations.toList(), transferred) + + val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), transferred) + if (transferred == remainder) { + + } + extractorNode.markTicked() } @@ -57,19 +62,21 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho if (powerCheck == 0) return@submit val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) - runPowerTransfer(solarPanelNode, destinations.toList(), powerCheck) + runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) } } // These methods are outside the class for speed -private fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } +fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } /** * Runs the power transfer from the source to the destinations. pending rewrite **/ -private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { +private fun runPowerTransfer(source: TransportNode, destinations: MutableList, availableTransferPower: Int): Int { + destinations.removeAll(source.getTransferableNodes().toSet()) if (destinations.isEmpty()) return availableTransferPower + val numDestinations = destinations.size var maximumResistance: Double = -1.0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index 3cde852119..ac6c3f7dd3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -4,6 +4,7 @@ import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -19,6 +20,16 @@ abstract class LinearNode, B: LinearNode< var axis by Delegates.notNull() override fun isTransferableTo(node: TransportNode): Boolean { + // This is probably very laggy + val endPoints = positions.flatMap { pos -> + axis.faces.toList().map { face -> getRelative(pos, face) } + }.filterNot { positions.contains(it) } + + when (node) { + is MultiNode<*, *> -> if (endPoints.none { node.positions.contains(it) }) return false + is SingleNode -> if (!endPoints.contains(node.position)) return false + } + return node !is PowerExtractorNode && node !is SolarPanelNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt index 6083c91cc0..259ef615f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt @@ -41,5 +41,7 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo return cachedTransferable } - fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationships.values.firstOrNull { it.offset == incoming.oppositeFace && it.canTransfer }?.other + fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationships.entries.firstOrNull { + it.value.offset == incoming.oppositeFace && it.value.canTransfer + }?.value?.other } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index e4a2b2fdbf..4d21b24a00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -1,12 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.manager.getPowerInputs import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt @@ -14,10 +18,8 @@ import kotlin.math.roundToInt class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE - constructor(network: PowerNodeManager, position: BlockKey) : this(network) { - this.position = position - network.extractors[position] = this - } + var tickNumber: Int = 0 + var tickInterval: Int = 1 /* * The extractor node should be allowed to transfer into any regular node. @@ -71,8 +73,15 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), * Returns the amount that couldn't be removed. **/ fun drawPower(amount: Int): Int { - val entities = relationships.mapNotNull { (it.value.other as? PowerInputNode)?.getPoweredEntities()?.randomOrNull() } //TODO + val entities = mutableListOf() + + for (relation in relationships) { + val node = relation.value.other + if (node !is PowerInputNode) continue + entities.addAll(node.getPoweredEntities()) + } + /* var remaining = amount while (remaining > 0) { @@ -89,6 +98,11 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), } } + */ + + val entity = entities.randomOrNull() ?: return amount + val remaining = entity.storage.removePower(amount) + return remaining } @@ -99,7 +113,9 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), fun getSourcePool() = relationships.mapNotNull { it.value.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } override fun toString(): String { - return "Extractor. found, can trasnsfer: ${getTransferPower()}" + val destinations = getPowerInputs(this) + debugAudience.highlightBlocks(destinations.map { it.getCenter() }, 30L) + return "Extractor. found, can trasnsfer: ${getTransferPower()}, numDestinations ${destinations.size}" } override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index d2b3b6f7b4..5b57b67343 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.util +import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode +import java.util.PriorityQueue import kotlin.math.roundToInt inline fun getNetworkDestinations(origin: TransportNode, check: (T) -> Boolean): ObjectOpenHashSet { @@ -30,11 +32,26 @@ inline fun getNetworkDestinations(origin: TransportNo * Uses the A* algorithm to find the shortest available path between these two nodes. **/ fun getIdealPath(from: TransportNode, to: TransportNode): Array? { - val queue = ArrayDeque(1) - queue.add(PathfindingNodeWrapper(from, null, 0, 0)) + // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. + val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } + // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. + val queueSet = IntOpenHashSet() + + fun queueAdd(wrapper: PathfindingNodeWrapper) { + queue.add(wrapper) + queueSet.add(wrapper.node.hashCode()) + } + + fun queueRemove(wrapper: PathfindingNodeWrapper) { + queue.remove(wrapper) + queueSet.remove(wrapper.node.hashCode()) + } + + queueAdd(PathfindingNodeWrapper(from, null, 0, 0)) - val visited = ArrayDeque() + val visited = ObjectOpenHashSet() + // Safeguard var iterations = 0 while (queue.isNotEmpty() && iterations < 150) { @@ -43,21 +60,21 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? if (current.node == to) return current.buildPath() - queue.remove(current) + queueRemove(current) visited.add(current) for (neighbor in getNeighbors(current)) { if (visited.contains(neighbor)) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) - val existingNeighbor = queue.firstOrNull { it.node === neighbor.node } - if (existingNeighbor != null) { + if (queueSet.contains(neighbor.node.hashCode())) { + val existingNeighbor = queue.first { it.node === neighbor.node } if (neighbor.g < existingNeighbor.g) { existingNeighbor.g = neighbor.g existingNeighbor.parent = neighbor.parent } } else { - queue.add(neighbor) + queueAdd(neighbor) } } } @@ -78,7 +95,7 @@ private fun getNeighbors(parent: PathfindingNodeWrapper): Array Date: Tue, 24 Sep 2024 01:52:13 -0500 Subject: [PATCH 199/500] fix vertical displays --- .../features/client/display/modular/display/Display.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index 04db94ea37..94bb3e4ebe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.rightFace @@ -14,9 +15,11 @@ import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Display.TextDisplay import net.minecraft.world.entity.EntityType +import org.bukkit.Axis.Y import org.bukkit.Bukkit import org.bukkit.Bukkit.getPlayer import org.bukkit.Color +import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.v1_20_R3.CraftServer import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay import org.bukkit.util.Transformation @@ -73,7 +76,7 @@ abstract class Display( } fun resetPosition(parent: TextDisplayHandler) { - val rightFace = parent.facing.rightFace + val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetBack val offsetY = offsetUp From 4e3af59f0419a351b99e75f47851ce6f47769fbd Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 24 Sep 2024 02:31:42 -0500 Subject: [PATCH 200/500] fix vertical displays pt 2 / 3, fix A* --- .../features/client/display/modular/TextDisplayHandler.kt | 4 +++- .../features/client/display/modular/display/Display.kt | 2 +- .../transport/node/type/power/PowerDirectionalNode.kt | 2 +- .../features/transport/node/util/NodePathfinding.kt | 8 ++++---- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index 814bccfc3c..1606e34c4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -3,7 +3,9 @@ package net.horizonsend.ion.server.features.client.display.modular import net.horizonsend.ion.server.features.client.display.modular.display.Display import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.TranslateMovement +import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import org.bukkit.Axis import org.bukkit.Location import org.bukkit.World import org.bukkit.block.BlockFace @@ -48,7 +50,7 @@ class TextDisplayHandler( } fun getLocation(): Location { - val rightFace = facing.rightFace + val rightFace = if (facing.axis == Axis.Y) BlockFace.NORTH else facing.rightFace val offsetX = rightFace.modX * offsetRight + facing.modX * offsetForward val offsetY = offsetUp diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index 94bb3e4ebe..6ddc91863c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -60,7 +60,7 @@ abstract class Display( fun setParent(parent: TextDisplayHandler) { this.handler = parent - val rightFace = parent.facing.rightFace + val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetBack val offsetY = offsetUp diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index 40b650578a..5ab641f56d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -62,6 +62,6 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( override fun toString(): String { val face = ADJACENT_BLOCK_FACES.random() - return "directional: $face is ${getForwardTransferable(face)}, $cachedTransferable" + return "${relationships.size} relations, Transferable to: ${getTransferableNodes()} directional: $face is ${getForwardTransferable(face)}, $cachedTransferable" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index 5b57b67343..5af905478f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -49,7 +49,7 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? queueAdd(PathfindingNodeWrapper(from, null, 0, 0)) - val visited = ObjectOpenHashSet() + val visited = IntOpenHashSet() // Safeguard var iterations = 0 @@ -61,10 +61,10 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? if (current.node == to) return current.buildPath() queueRemove(current) - visited.add(current) + visited.add(current.node.hashCode()) for (neighbor in getNeighbors(current)) { - if (visited.contains(neighbor)) continue + if (visited.contains(neighbor.node.hashCode())) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) if (queueSet.contains(neighbor.node.hashCode())) { @@ -83,7 +83,7 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? } // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution -private fun getNeighbors(parent: PathfindingNodeWrapper): Array { +fun getNeighbors(parent: PathfindingNodeWrapper): Array { val parentParent = parent.parent val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { parent.node.getNextNodes(parentParent.node) From 70cde6d085fc901fa03113ceb260a0e33192cb9d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 25 Sep 2024 19:54:13 -0500 Subject: [PATCH 201/500] fix dupe --- .../server/command/admin/IonChunkCommand.kt | 23 +++++++---- .../entity/type/power/PowerStorage.kt | 8 ++-- .../type/power/storage/PowerBankMultiblock.kt | 11 +++++- .../node/manager/PowerNodeManager.kt | 39 ++++++++++--------- .../node/type/power/PowerInputNode.kt | 3 +- 5 files changed, 54 insertions(+), 30 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 4c7f858391..40cad85f0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,15 +4,12 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager +import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion @@ -107,7 +104,7 @@ object IonChunkCommand : SLCommand() { @Subcommand("rebuild nodes") @CommandCompletion("power") /* |item|gas") */ - fun rebuildNodes(sender: Player, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { + fun rebuildNodes(sender: Player, network: NetworkType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) @@ -130,7 +127,7 @@ object IonChunkCommand : SLCommand() { } @Subcommand("get node key") - fun getNode(sender: Player, key: Long, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { + fun getNode(sender: Player, key: Long, network: NetworkType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) @@ -138,7 +135,7 @@ object IonChunkCommand : SLCommand() { } @Subcommand("get node look") - fun getNode(sender: Player, network: NetworkType) = CoroutineScope(Dispatchers.Default + Job()).launch { + fun getNode(sender: Player, network: NetworkType) { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() val grid = network.get(ionChunk) @@ -146,4 +143,16 @@ object IonChunkCommand : SLCommand() { sender.information("Targeted node: ${grid.nodes[key]}") } + + @Subcommand("tick extractor") + fun onTick(sender: Player) { + val targeted = sender.getTargetBlock(null, 10) + val ionChunk = targeted.chunk.ion() + val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val node = grid.nodes[key] + if (node !is PowerExtractorNode) return + grid.tickExtractor(node) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index 91e32f4cb8..158ccee50c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -4,8 +4,10 @@ import java.util.concurrent.ConcurrentHashMap class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacity: Int) { private var backingPower = amount + @Synchronized get + @Synchronized set - val mutex = Any() + private val mutex = Any() fun isEmpty() = getPower() <= 0 fun isFull() = getPower() >= capacity @@ -29,7 +31,7 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit **/ fun addPower(amount: Int): Int { val newAmount = synchronized(mutex) { - val newAmount = getPower() + amount + val newAmount = backingPower + amount val corrected = newAmount.coerceIn(0, capacity) backingPower = corrected @@ -46,7 +48,7 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit **/ fun removePower(amount: Int): Int { val newAmount = synchronized(mutex) { - val newAmount = getPower() - amount + val newAmount = backingPower - amount val corrected = newAmount.coerceIn(0, capacity) backingPower = corrected diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 96e5152168..06125de4e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers.newMultiblockSignOverlay import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock @@ -10,6 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -20,10 +22,12 @@ import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataType -abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { abstract val tierMaterial: Material override val name = "powerbank" @@ -86,6 +90,11 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM } } + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val b = getMultiblockEntity(sign) ?: return + player.information("b: ${b.storage.getPower()}") + } + override fun createEntity( manager: MultiblockManager, data: PersistentMultiblockData, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 1143a3136d..8ee76c4cb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -42,19 +42,30 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho solarPanels.forEach(::tickSolarPanel) } - private fun tickExtractor(extractorNode: PowerExtractorNode) = NewTransport.executor.submit { + fun tickExtractor(extractorNode: PowerExtractorNode) = NewTransport.executor.submit { val powerCheck = extractorNode.getTransferPower() if (powerCheck == 0) return@submit + extractorNode.markTicked() + + val source = extractorNode.getSourcePool().filterNot { it.storage.isEmpty() }.randomOrNull() ?: return@submit + val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) - val transferred = extractorNode.getTransferPower() + destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) - val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), transferred) - if (transferred == remainder) { + if (destinations.isEmpty()) return@submit + val transferred = minOf(source.storage.getPower(), powerCheck) + val notRemoved = source.storage.removePower(transferred) + val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) + + if (transferred == remainder) { + //TODO skip growing number of ticks if nothing to do } - extractorNode.markTicked() + if (remainder > 0) { + source.storage.addPower(remainder) + } } private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { @@ -73,18 +84,17 @@ fun getPowerInputs(origin: TransportNode) = getNetworkDestinations, availableTransferPower: Int): Int { - destinations.removeAll(source.getTransferableNodes().toSet()) +private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { if (destinations.isEmpty()) return availableTransferPower val numDestinations = destinations.size - var maximumResistance: Double = -1.0 - val paths: Array?> = Array(numDestinations) { runCatching { getIdealPath(source, destinations[it]) }.getOrNull() } + var maximumResistance: Double = -1.0 + // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { val res = calculatePathResistance(paths[it]) @@ -111,23 +121,16 @@ private fun runPowerTransfer(source: TransportNode, destinations: MutableList Date: Thu, 26 Sep 2024 00:52:27 -0500 Subject: [PATCH 202/500] fix times power isn't transferring, more robust relation system --- .../server/command/admin/IonChunkCommand.kt | 10 ++ .../server/features/transport/NewTransport.kt | 2 +- .../transport/node/NodeRelationship.kt | 13 --- .../features/transport/node/RelationHolder.kt | 96 +++++++++++++++++++ .../features/transport/node/TransportNode.kt | 77 +++++++-------- .../node/manager/PowerNodeManager.kt | 3 +- .../features/transport/node/type/MultiNode.kt | 16 +--- .../transport/node/type/SingleNode.kt | 14 --- .../node/type/fluid/FluidInputNode.kt | 4 - .../node/type/fluid/FluidJunctionNode.kt | 3 +- .../transport/node/type/general/LinearNode.kt | 15 +-- .../type/power/InvertedDirectionalNode.kt | 6 +- .../node/type/power/PowerDirectionalNode.kt | 6 +- .../node/type/power/PowerExtractorNode.kt | 77 ++++++++------- .../server/miscellaneous/utils/Collections.kt | 1 + 15 files changed, 198 insertions(+), 145 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 40cad85f0c..04ad62b3de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -144,6 +144,16 @@ object IonChunkCommand : SLCommand() { sender.information("Targeted node: ${grid.nodes[key]}") } + @Subcommand("get node look relations") + fun getNodeRelations(sender: Player, network: NetworkType) { + val targeted = sender.getTargetBlock(null, 10) + val ionChunk = targeted.chunk.ion() + val grid = network.get(ionChunk) + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + sender.information("${grid.nodes[key]?.getTransferableNodes()?.joinToString { it.javaClass.simpleName }}") + } + @Subcommand("tick extractor") fun onTick(sender: Player) { val targeted = sender.getTargetBlock(null, 10) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index e6c30d334b..76da821c7f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -32,8 +32,8 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } override fun onDisable() { + if (::monitorThread.isInitialized) monitorThread.cancel() if (::executor.isInitialized) executor.shutdown() - if (::monitorThread.isInitialized) executor.shutdown() } fun registerTransportManager(manager: TransportManager) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 258a270a61..48d9732321 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.BlockFace /** @@ -22,18 +21,6 @@ data class NodeRelationship( holder.refreshTransferCache() other.refreshTransferCache() } - - companion object { - fun create(point: BlockKey, holder: TransportNode, other: TransportNode, nodeTwoOffset: BlockFace) { - val holderToOther = holder.isTransferableTo(other) - val otherToHolder = other.isTransferableTo(holder) - - holder.relationships[point] = NodeRelationship(holder, other, nodeTwoOffset, holderToOther) - other.relationships[point] = NodeRelationship(other, holder, nodeTwoOffset.oppositeFace, otherToHolder) - holder.refreshTransferCache() - other.refreshTransferCache() - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt new file mode 100644 index 0000000000..b4b551ae0f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt @@ -0,0 +1,96 @@ +package net.horizonsend.ion.server.features.transport.node + +import it.unimi.dsi.fastutil.ints.IntOpenHashSet +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace +import java.util.concurrent.BlockingDeque +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.LinkedBlockingDeque + +class RelationHolder(val node: TransportNode) { + private val relationships = ConcurrentHashMap>() + private val containsCache = ConcurrentHashMap() + + /** + * Create a relationship between this node and the provided node + * + * If neither side can transfer, a relation will not be created + **/ + fun addRelationship(other: TransportNode, holderPosition: BlockKey, otherPosition: BlockKey, nodeTwoOffset: BlockFace) { + // Do not add duplicates + val existingAt = relationships[holderPosition] + if (existingAt != null && existingAt.any { it.other == other }) return + + create(other, holderPosition, otherPosition, nodeTwoOffset) + other.neighborChanged(node) + } + + /** + * @param other The node this relation is being created with + * @param holderPosition The position that this node was created from + * @param otherPosition The position that the other node was found at + * @param nodeTwoOffset The direction that the other node was found + **/ + private fun create(other: TransportNode, holderPosition: BlockKey, otherPosition: BlockKey, nodeTwoOffset: BlockFace) { + val holderToOther = node.isTransferableTo(other) + val otherToHolder = other.isTransferableTo(node) + + // Add relation from this node to the other + add(holderPosition, NodeRelationship(node, other, nodeTwoOffset, holderToOther)) + // Add relation from the other to this + other.relationHolder.add(otherPosition, NodeRelationship(other, node, nodeTwoOffset.oppositeFace, otherToHolder)) + + node.refreshTransferCache() + other.refreshTransferCache() + } + + fun add(point: BlockKey, relation: NodeRelationship) { + relationships.getOrPut(point) { LinkedBlockingDeque() }.add(relation) + containsCache.getOrPut(point) { IntOpenHashSet() }.add(relation.other.hashCode()) + } + + fun remove(point: BlockKey, relation: NodeRelationship) { + relationships[point]?.remove(relation) + containsCache[point]?.remove(relation.other.hashCode()) + } + + fun removeAll(point: BlockKey): BlockingDeque? { + return relationships.remove(point) + } + + fun clear() { + relationships.values.forEach { + for (nodeRelationship in it) { + nodeRelationship.breakUp() + } + } + } + + fun removeRelationship(other: TransportNode) { + // Handle duplicate cases + for (key in relationships.keys.filter { containsCache.contains(other.hashCode()) }) { + relationships[key]?.removeAll { it.other == other } + } + + // Notify of neighbor change + other.neighborChanged(node) + } + + fun getAllOthers(): Set { + val others = ObjectOpenHashSet() + + for (key in relationships.keys) { + for (relation in relationships[key]!!) { + others.add(relation) + } + } + + return others + } + + fun raw() = relationships + + fun hasRelationAt(position: BlockKey): Boolean = relationships.containsKey(position) + fun hasRelationAtWith(point: BlockKey, other: TransportNode): Boolean = containsCache[point]?.contains(other.hashCode()) ?: false +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index f9336710a6..0c862bc4f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -4,13 +4,14 @@ import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import java.util.concurrent.ConcurrentHashMap /** * Represents a single node, or step, in transport transportNetwork @@ -21,50 +22,19 @@ abstract class TransportNode : PDCSerializable = ConcurrentHashMap() + val relationHolder = RelationHolder(this) /** * Break all relations between this node and others **/ - fun clearRelations() { - relationships.values.forEach { - it.breakUp() - } - } - - /** - * Create a relationship between this node and the provided node - * - * If neither side can transfer, a relation will not be created - **/ - fun addRelationship(point: BlockKey, other: TransportNode, offset: BlockFace) { - // Do not add duplicates - val existing = relationships[point] - if (existing?.other == other) return - - NodeRelationship.create(point, this, other, offset) - other.neighborChanged(this) - } - - fun removeRelationship(other: TransportNode) { - // Handle duplicate cases - val toOther = relationships.filter { it.value.other == other } - - toOther.keys.forEach { relationships.remove(it) } + fun clearRelations() = relationHolder.clear() - // Notify of neighbor change - other.neighborChanged(this) - } + fun removeRelationship(other: TransportNode) = relationHolder.removeRelationship(other) - fun removeRelationship(at: BlockKey) { - // Handle duplicate cases - val toOther = relationships[at] - toOther?.breakUp() + fun removeRelationships(at: BlockKey) = relationHolder.removeAll(at) - // Notify of neighbor change - toOther?.other?.neighborChanged(this) - } + fun addRelationship(other: TransportNode, holderPosition: BlockKey, otherPosition: BlockKey, nodeTwoOffset: BlockFace) = + relationHolder.addRelationship(other, holderPosition, otherPosition, nodeTwoOffset) /** * Returns whether this node may transport to the provided node @@ -85,9 +55,9 @@ abstract class TransportNode : PDCSerializable { - return relationships.mapNotNullTo(mutableSetOf()) { relation -> + return relationHolder.getAllOthers().mapNotNullTo(mutableSetOf()) { relation -> // The other side of the relation, only if transfer is possible between this node and it. Double check if it is dead as well - relation.value.other.takeIf { other -> relation.value.canTransfer && !other.isDead } + relation.other.takeIf { relation.canTransfer && !it.isDead } } } @@ -113,10 +83,25 @@ abstract class TransportNode : PDCSerializable>() fun getRelationshipWith(other: TransportNode): Map { - return relationCache.getOrPut(other) { relationships.filter { it.value.other == other } } + return relationCache.getOrPut(other) { + val cache = mutableMapOf() + for ((key, relations) in relationHolder.raw()) { + if (!relationHolder.hasRelationAtWith(key, other)) continue + cache[key] = relations.firstOrNull { it.other == other } ?: continue + } + + cache + } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 8ee76c4cb5..68bb521947 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Future import kotlin.math.roundToInt class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { @@ -42,7 +43,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho solarPanels.forEach(::tickSolarPanel) } - fun tickExtractor(extractorNode: PowerExtractorNode) = NewTransport.executor.submit { + fun tickExtractor(extractorNode: PowerExtractorNode): Future<*> = NewTransport.executor.submit { val powerCheck = extractorNode.getTransferPower() if (powerCheck == 0) return@submit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt index 731ccf22bf..606d9f31e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt @@ -60,17 +60,6 @@ abstract class MultiNode, Z: MultiNode> : Tran new.positions.forEach { new.buildRelations(it) } } - override fun buildRelations(position: BlockKey) { - for (offset in ADJACENT_BLOCK_FACES) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = manager.getNode(offsetKey) ?: continue - - if (this == neighborNode) continue - - addRelationship(position, neighborNode, offset) - } - } - fun rebuildRelations() { clearRelations() @@ -89,7 +78,7 @@ abstract class MultiNode, Z: MultiNode> : Tran // Remove the position from this node positions.remove(position) - removeRelationship(position) + removeRelationships(position) if (separateNode(this)) { positions.clear() @@ -125,9 +114,10 @@ abstract class MultiNode, Z: MultiNode> : Tran positions.forEach { newNode.addPosition(it) - newNode.buildRelations(it) } + newNode.rebuildRelations() + return newNode } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 07cfc946a9..93c60f1ad8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -1,10 +1,8 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import kotlin.properties.Delegates @@ -18,18 +16,6 @@ abstract class SingleNode : TransportNode() { manager.nodes[position] = this } - override fun buildRelations(position: BlockKey) { - for (offset in ADJACENT_BLOCK_FACES) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = manager.getNode(offsetKey) ?: continue - - if (this == neighborNode) return - - // Add a relationship, if one should be added - addRelationship(position, neighborNode, offset) - } - } - override fun onPlace(position: BlockKey) { buildRelations(position) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt index b4031978b0..118413b615 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt @@ -21,10 +21,6 @@ class FluidInputNode(override val manager: FluidNodeManager) : SingleNode() { return false } - override fun buildRelations(position: BlockKey) { - super.buildRelations(position) - } - override fun storeData(persistentDataContainer: PersistentDataContainer) { persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt index 6dcb4d686e..1d0edde16c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i class FluidJunctionNode(network: FluidNodeManager) : JunctionNode(network) { override val type: NodeType = NodeType.FLUID_JUNCTION @@ -19,7 +20,7 @@ class FluidJunctionNode(network: FluidNodeManager) : JunctionNode "[${toVec3i(key)} = (${relations.joinToString { it.other.toString() }}(]" }} """.trimIndent() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index ac6c3f7dd3..1aae98b4a5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -12,12 +12,14 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Axis +import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates abstract class LinearNode, B: LinearNode>(override val manager: T) : MultiNode() { var axis by Delegates.notNull() + override val relationOffsets: Set get() = axis.faces.toList().toSet() override fun isTransferableTo(node: TransportNode): Boolean { // This is probably very laggy @@ -33,17 +35,6 @@ abstract class LinearNode, B: LinearNode< return node !is PowerExtractorNode && node !is SolarPanelNode } - override fun buildRelations(position: BlockKey) { - for (offset in axis.faces.toList()) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = manager.getNode(offsetKey) ?: continue - - if (this == neighborNode) continue - - addRelationship(position, neighborNode, offset) - } - } - override fun loadData(persistentDataContainer: PersistentDataContainer) { val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) coveredPositions?.let { positions.addAll(it.asIterable()) } @@ -80,5 +71,5 @@ abstract class LinearNode, B: LinearNode< return this } - override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationships.size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" + override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationHolder.getAllOthers().size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt index 259ef615f5..62872a0efa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt @@ -41,7 +41,7 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo return cachedTransferable } - fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationships.entries.firstOrNull { - it.value.offset == incoming.oppositeFace && it.value.canTransfer - }?.value?.other + fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { + it.offset == incoming.oppositeFace && it.canTransfer + }?.other } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index 5ab641f56d..bcc0b743a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -58,10 +58,12 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( return cachedTransferable } - fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationships.values.firstOrNull { it.offset == incoming.oppositeFace && it.canTransfer }?.other + fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { + it.offset == incoming.oppositeFace && it.canTransfer + }?.other override fun toString(): String { val face = ADJACENT_BLOCK_FACES.random() - return "${relationships.size} relations, Transferable to: ${getTransferableNodes()} directional: $face is ${getForwardTransferable(face)}, $cachedTransferable" + return "${relationHolder.getAllOthers().size} relations, Transferable to: ${getTransferableNodes()} directional: $face is ${getForwardTransferable(face)}, $cachedTransferable" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 4d21b24a00..bb914b16f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager @@ -68,49 +67,49 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), super.handlePositionRemoval(position) } - /** - * Attempts to draw power from connected inputs. - * Returns the amount that couldn't be removed. - **/ - fun drawPower(amount: Int): Int { - val entities = mutableListOf() - - for (relation in relationships) { - val node = relation.value.other - if (node !is PowerInputNode) continue - entities.addAll(node.getPoweredEntities()) - } - - /* - var remaining = amount - - while (remaining > 0) { - val available = entities.filterNot { it.storage.isEmpty() } - if (available.isEmpty()) break - - val minPower = entities.minOf { it.storage.getPower() } - val idealShare = remaining / available.size - val toRemove = minOf(idealShare, minPower) - - available.forEach { - val r = it.storage.removePower(toRemove) - remaining -= (toRemove - r) - } - } - - */ - - val entity = entities.randomOrNull() ?: return amount - val remaining = entity.storage.removePower(amount) - - return remaining - } +// /** +// * Attempts to draw power from connected inputs. +// * Returns the amount that couldn't be removed. +// **/ +// fun drawPower(amount: Int): Int { +// val entities = mutableListOf() +// +// for (relation in relationships) { +// val node = relation.value.other +// if (node !is PowerInputNode) continue +// entities.addAll(node.getPoweredEntities()) +// } +// +// /* +// var remaining = amount +// +// while (remaining > 0) { +// val available = entities.filterNot { it.storage.isEmpty() } +// if (available.isEmpty()) break +// +// val minPower = entities.minOf { it.storage.getPower() } +// val idealShare = remaining / available.size +// val toRemove = minOf(idealShare, minPower) +// +// available.forEach { +// val r = it.storage.removePower(toRemove) +// remaining -= (toRemove - r) +// } +// } +// +// */ +// +// val entity = entities.randomOrNull() ?: return amount +// val remaining = entity.storage.removePower(amount) +// +// return remaining +// } override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 0 } - fun getSourcePool() = relationships.mapNotNull { it.value.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } + fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } override fun toString(): String { val destinations = getPowerInputs(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt index a2b3da242c..c573181501 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Collections.kt @@ -130,6 +130,7 @@ inline fun Map.filterKeysIsInstance(): Map { } inline fun Collection.averageBy(transform: (T) -> Double): Double { + if (isEmpty()) return 0.0 if (size == 1) { return transform(first()) } var total = 0.0 From 2d940acd6c39a74f021ebebf11ed8fb1dc4a1cda Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 26 Sep 2024 01:05:35 -0500 Subject: [PATCH 203/500] have pistons update nodes --- .../features/transport/GlobalNodeManager.kt | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt index 42fe428663..e7cb21b033 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ @@ -13,6 +14,8 @@ import org.bukkit.block.Block import org.bukkit.block.data.BlockData import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPistonExtendEvent +import org.bukkit.event.block.BlockPistonRetractEvent import org.bukkit.event.block.BlockPlaceEvent object GlobalNodeManager : SLEventListener() { @@ -26,16 +29,32 @@ object GlobalNodeManager : SLEventListener() { @EventHandler fun onBlockPlace(event: BlockPlaceEvent) { - val world = event.block.world + handleBlockChange(event.block) + } - handleBlockChange(world, event.block) + @EventHandler + fun onPistonExtend(event: BlockPistonExtendEvent) { + // Delay 1 tick + Tasks.sync { event.blocks.forEach { + handleBlockRemoval(it.world, toBlockKey(it.x, it.y, it.z)) + handleBlockChange(it) + }} } - fun handleBlockChange(world: World, new: Block) { + @EventHandler + fun onPistonRetract(event: BlockPistonRetractEvent) { + // Delay 1 tick + Tasks.sync { event.blocks.forEach { + handleBlockRemoval(it.world, toBlockKey(it.x, it.y, it.z)) + handleBlockChange(it) + }} + } + + fun handleBlockChange(new: Block) { val chunkX = new.x.shr(4) val chunkZ = new.z.shr(4) - val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return + val chunk = new.world.ion.getChunk(chunkX, chunkZ) ?: return chunk.transportNetwork.processBlockChange(new) } @@ -69,9 +88,9 @@ object GlobalNodeManager : SLEventListener() { chunk.transportNetwork.refreshBlock(position) } - fun handleBlockAdditions(world: World, newBlocks: Iterable) { + fun handleBlockAdditions(newBlocks: Iterable) { for (new in newBlocks) { - handleBlockChange(world, new) + handleBlockChange(new) } } From 6550cd2a970a73ac681e9470bcebff32fcc032a9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 26 Sep 2024 01:47:53 -0500 Subject: [PATCH 204/500] fix rebuild chunk --- .../server/command/admin/IonChunkCommand.kt | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 04ad62b3de..8716039682 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtrac import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text @@ -106,21 +107,24 @@ object IonChunkCommand : SLCommand() { @CommandCompletion("power") /* |item|gas") */ fun rebuildNodes(sender: Player, network: NetworkType) { val ionChunk = sender.chunk.ion() - val grid = network.get(ionChunk) - grid.nodes.clear() + Tasks.async { + val grid = network.get(ionChunk) - when (grid) { - is PowerNodeManager -> { - grid.extractors.clear() - grid.solarPanels.clear() + grid.nodes.clear() + + when (grid) { + is PowerNodeManager -> { + grid.extractors.clear() + grid.solarPanels.clear() + } } - } - for (x in ionChunk.originX ..ionChunk.originX + 15) { - for (z in ionChunk.originZ..ionChunk.originZ + 15) { - for (y in ionChunk.world.minHeight until ionChunk.world.maxHeight) { - grid.createNodeFromBlock(sender.world.getBlockAt(x, y, z)) + for (x in ionChunk.originX ..ionChunk.originX + 15) { + for (z in ionChunk.originZ..ionChunk.originZ + 15) { + for (y in ionChunk.world.minHeight until ionChunk.world.maxHeight) { + grid.createNodeFromBlock(sender.world.getBlockAt(x, y, z)) + } } } } From b3738f0e264b858b9808abbf390d2aee51f38952 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 26 Sep 2024 13:48:27 -0500 Subject: [PATCH 205/500] fix bugs with directional nodes --- .../server/command/admin/IonChunkCommand.kt | 58 +++++++++- .../custom/items/misc/MultimeterItem.kt | 102 +++++++++++++++++- .../transport/node/type/power/EndRodNode.kt | 2 +- .../type/power/InvertedDirectionalNode.kt | 4 +- .../node/type/power/PowerDirectionalNode.kt | 10 +- .../node/type/power/PowerExtractorNode.kt | 2 +- .../node/type/power/PowerFlowMeter.kt | 2 +- .../node/type/power/PowerInputNode.kt | 2 +- .../node/type/power/PowerPathfindingNode.kt | 2 +- .../node/type/power/SolarPanelNode.kt | 2 +- .../transport/node/type/power/SpongeNode.kt | 2 +- .../transport/node/util/NodePathfinding.kt | 6 +- 12 files changed, 175 insertions(+), 19 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 8716039682..34d2f71dea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,12 +4,17 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion @@ -158,7 +163,7 @@ object IonChunkCommand : SLCommand() { sender.information("${grid.nodes[key]?.getTransferableNodes()?.joinToString { it.javaClass.simpleName }}") } - @Subcommand("tick extractor") + @Subcommand("test extractor") fun onTick(sender: Player) { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() @@ -169,4 +174,55 @@ object IonChunkCommand : SLCommand() { if (node !is PowerExtractorNode) return grid.tickExtractor(node) } + + @Subcommand("test pathfinding") + fun onTestPathfinding(sender: Player) { + val targeted = sender.getTargetBlock(null, 10) + val ionChunk = targeted.chunk.ion() + val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") + val transferable = at.getTransferableNodes() + + fun getNext(node: TransportNode): Collection { + at as PowerPathfindingNode + return at.getNextNodes(node, null) + } + + sender.information("Transferable nodes from ${at.javaClass.simpleName}") + sender.information(transferable.joinToString(separator = "\n") { next -> + "${next.javaClass.simpleName} -> [${getNext(next).joinToString { it.javaClass.simpleName }}]" + }) + } + + @Subcommand("test flood") + fun onTestFloodFill(sender: Player) { + val targeted = sender.getTargetBlock(null, 10) + val ionChunk = targeted.chunk.ion() + val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") + + val visitQueue = ArrayDeque() + val visitedSet = ObjectOpenHashSet() + val destinations = ObjectOpenHashSet() + + visitQueue.addAll(at.cachedTransferable) + var iterations = 0L + + while (visitQueue.isNotEmpty()) { + iterations++ + val currentNode = visitQueue.removeFirst() + Tasks.syncDelay(iterations) { sender.highlightBlock(currentNode.getCenter(), 5L) } + visitedSet.add(currentNode) + + if (currentNode is PowerInputNode) { + destinations.add(currentNode) + } + + visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index c139cf5195..b2f9fdeb43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -1,17 +1,23 @@ package net.horizonsend.ion.server.features.custom.items.misc +import it.unimi.dsi.fastutil.ints.IntOpenHashSet import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.node.util.PathfindingNodeWrapper import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.node.util.getIdealPath +import net.horizonsend.ion.server.features.transport.node.util.getHeuristic import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_VARIANT import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -30,6 +36,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG +import java.util.PriorityQueue object MultimeterItem : CustomItem("Multimeter") { override fun constructItemStack(): ItemStack { @@ -83,7 +90,7 @@ object MultimeterItem : CustomItem("Multimeter") { val firstNode = networkType.get(firstChunk).getNode(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") val secondNode = networkType.get(secondChunk).getNode(secondPoint) ?: return audience.information("There is no node at ${toVec3i(secondPoint)}") - val path = getIdealPath(firstNode, secondNode) + val path = getIdealPath(audience, firstNode, secondNode) val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${secondNode.javaClass.simpleName} at ${toVec3i(secondPoint)} is $resistance") } @@ -99,4 +106,95 @@ object MultimeterItem : CustomItem("Multimeter") { tryCheckResistance(audience, world, itemStack) } + + /** + * Uses the A* algorithm to find the shortest available path between these two nodes. + **/ + private fun getIdealPath(audience: Audience, from: TransportNode, to: TransportNode): Array? { + // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. + val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } + // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. + val queueSet = IntOpenHashSet() + + fun queueAdd(wrapper: PathfindingNodeWrapper) { + queue.add(wrapper) + queueSet.add(wrapper.node.hashCode()) + } + + fun queueRemove(wrapper: PathfindingNodeWrapper) { + queue.remove(wrapper) + queueSet.remove(wrapper.node.hashCode()) + } + + queueAdd(PathfindingNodeWrapper(from, null, 0, 0)) + + val visited = IntOpenHashSet() + + // Safeguard + var iterations = 0L + + while (queue.isNotEmpty() && iterations < 150) { + iterations++ + val current = queue.minBy { it.f } + Tasks.syncDelay(iterations) { audience.highlightBlock(current.node.getCenter(), 5L) } + audience.information("current: ${current.node.javaClass.simpleName} at ${current.node.getCenter()}") + if (current.node == to) return current.buildPath() + + queueRemove(current) + visited.add(current.node.hashCode()) + + val neighbors = getNeighborsB(audience, current, to) + if (neighbors.isEmpty()) audience.userError("Empty neighbors") + + for (newNeighbor in neighbors) { + audience.information("new neighbor: ${newNeighbor.node} at ${newNeighbor.node.getCenter()}") + if (visited.contains(newNeighbor.node.hashCode())) { + audience.information("conmtinue") + continue + } + + newNeighbor.f = (newNeighbor.g + getHeuristic(newNeighbor, to)) + + if (queueSet.contains(newNeighbor.node.hashCode())) { + audience.information("Existing in queue") + val existingNeighbor = queue.first { it.node === newNeighbor.node } + if (newNeighbor.g < existingNeighbor.g) { + existingNeighbor.g = newNeighbor.g + existingNeighbor.f = newNeighbor.f + existingNeighbor.parent = newNeighbor.parent + } + } else { + audience.information("Adding to queue") + queueAdd(newNeighbor) + } + } + } + + audience.userError("Exhausted queue, $iterations") + + return null + } + + // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution + private fun getNeighborsB(audience: Audience, parent: PathfindingNodeWrapper, destination: TransportNode): Array { + val parentParent = parent.parent + audience.information("Parent: ${parent.node.getTransferableNodes()}") + + val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { + parent.node.getNextNodes(parentParent.node, destination) + } else parent.node.cachedTransferable + + audience.information("New transferable: ${transferable.joinToString { it.javaClass.simpleName }}") + + return Array(transferable.size) { + val neighbor = transferable[it] + + PathfindingNodeWrapper( + node = neighbor, + parent = parent, + g = parent.g + parent.node.getDistance(neighbor).toInt(), + f = 1 + ) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt index 1ff1dcd87e..25391d56d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt @@ -21,5 +21,5 @@ class EndRodNode(network: PowerNodeManager) : LinearNode(position, data.facing.axis, type, handleRelationships = false) } - override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt index 62872a0efa..0cfa41d3a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt @@ -29,7 +29,9 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo return 1 } - override fun getNextNodes(previous: TransportNode): ArrayDeque { + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque { + if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) + // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. // So there will likely only be a single relation to this val direction = previous.getRelationshipWith(this).values diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index bcc0b743a6..c3306ce60c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material import org.bukkit.block.BlockFace @@ -46,7 +45,9 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( return 1 } - override fun getNextNodes(previous: TransportNode): ArrayDeque { + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque { + if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) + // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. // So there will likely only be a single relation to this val direction = previous.getRelationshipWith(this).values @@ -59,11 +60,10 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( } fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { - it.offset == incoming.oppositeFace && it.canTransfer + it.offset == incoming && it.canTransfer }?.other override fun toString(): String { - val face = ADJACENT_BLOCK_FACES.random() - return "${relationHolder.getAllOthers().size} relations, Transferable to: ${getTransferableNodes()} directional: $face is ${getForwardTransferable(face)}, $cachedTransferable" + return "${relationHolder.getAllOthers().size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }}" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index bb914b16f5..b26f7b55d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -117,6 +117,6 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), return "Extractor. found, can trasnsfer: ${getTransferPower()}, numDestinations ${destinations.size}" } - override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt index df6f570591..28d7a1f5f3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt @@ -135,5 +135,5 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(), Pow return 1 } - override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt index 4429fa2b6d..62ca399258 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt @@ -85,7 +85,7 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(), Pow return 0 } - override fun getNextNodes(previous: TransportNode): ArrayDeque { + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque { return ArrayDeque(0) // Can't transfer to anything } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt index 714699cd65..59167601c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt @@ -6,5 +6,5 @@ interface PowerPathfindingNode { /** * For use in pathfinding. When entering from previous node, get the list of available next nodes. Mostly used by the flood fill. **/ - fun getNextNodes(previous: TransportNode): ArrayDeque + fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt index 3a5af1e608..f465a68d8f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt @@ -262,7 +262,7 @@ class SolarPanelNode(override val manager: PowerNodeManager) : MultiNode = cachedTransferable + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable override fun toString(): String = "(SOLAR PANEL NODE:" + " Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, " + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt index c44b0b48da..dd19c44842 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt @@ -20,7 +20,7 @@ class SpongeNode(network: PowerNodeManager) : JunctionNode(position, type, handleRelationships = false) } - override fun getNextNodes(previous: TransportNode): ArrayDeque = cachedTransferable + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes) location = ${toVec3i(positions.random())}" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index 5af905478f..8904fc92f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -63,7 +63,7 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? queueRemove(current) visited.add(current.node.hashCode()) - for (neighbor in getNeighbors(current)) { + for (neighbor in getNeighbors(current, to)) { if (visited.contains(neighbor.node.hashCode())) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) @@ -83,10 +83,10 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? } // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution -fun getNeighbors(parent: PathfindingNodeWrapper): Array { +fun getNeighbors(parent: PathfindingNodeWrapper, destination: TransportNode): Array { val parentParent = parent.parent val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { - parent.node.getNextNodes(parentParent.node) + parent.node.getNextNodes(parentParent.node, destination) } else parent.node.cachedTransferable return Array(transferable.size) { From 86bd9af3989f44fda7b60154302529a48263112a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 27 Sep 2024 12:49:39 -0500 Subject: [PATCH 206/500] simplify placement of flow meters --- .../transport/node/type/SingleNode.kt | 11 ++++++++ .../node/type/general/DirectionalNode.kt | 26 +++++++++++++++++++ .../type/power/InvertedDirectionalNode.kt | 11 -------- .../node/type/power/PowerDirectionalNode.kt | 5 ++-- .../node/type/power/PowerExtractorNode.kt | 11 -------- .../node/type/power/PowerFlowMeter.kt | 24 +++-------------- .../node/type/power/PowerNodeFactory.kt | 9 ++----- .../transport/node/util/NodeFactory.kt | 12 +++++++++ 8 files changed, 57 insertions(+), 52 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt index 93c60f1ad8..31ce47446c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt @@ -1,9 +1,12 @@ package net.horizonsend.ion.server.features.transport.node.type import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates /** @@ -29,4 +32,12 @@ abstract class SingleNode : TransportNode() { override fun getCenter(): Vec3i { return toVec3i(position) } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt new file mode 100644 index 0000000000..8b154f70e4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.transport.node.type.general + +import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.AXIS +import org.bukkit.block.BlockFace +import org.bukkit.block.BlockFace.NORTH +import org.bukkit.persistence.PersistentDataContainer + +abstract class DirectionalNode : SingleNode() { + lateinit var direction: BlockFace + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + super.loadData(persistentDataContainer) + direction = persistentDataContainer.getOrDefault(AXIS, directionPDC, NORTH) + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + super.storeData(persistentDataContainer) + persistentDataContainer.set(AXIS, directionPDC, direction) + } + + companion object { + private val directionPDC = EnumDataType(BlockFace::class.java) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt index 0cfa41d3a3..e5cc3e22e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt @@ -4,10 +4,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_INVERSE_DIRECTIONAL_NODE @@ -17,14 +14,6 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo return node !is PowerExtractorNode && node !is SolarPanelNode } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 1 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index c3306ce60c..e265ed4b77 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -10,7 +10,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { @@ -28,12 +27,12 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( } override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) + super.storeData(persistentDataContainer) persistentDataContainer.set(NamespacedKeys.NODE_VARIANT, materialDataType, variant) } override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! + super.loadData(persistentDataContainer) variant = persistentDataContainer.get(NamespacedKeys.NODE_VARIANT, materialDataType)!! } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index b26f7b55d2..48a7fba980 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -7,11 +7,8 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.manager.getPowerInputs import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { @@ -44,14 +41,6 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - override fun loadIntoNetwork() { super.loadIntoNetwork() manager.extractors[position] = this diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt index 28d7a1f5f3..698a64cddb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.type.power -import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren @@ -10,8 +9,7 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerF import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component @@ -20,19 +18,15 @@ import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW import org.bukkit.block.BlockFace -import org.bukkit.block.BlockFace.NORTH -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { +class PowerFlowMeter(override val manager: PowerNodeManager) : DirectionalNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_FLOW_METER + constructor(network: PowerNodeManager, position: BlockKey, direction: BlockFace) : this(network) { this.position = position this.direction = direction } - lateinit var direction: BlockFace - /* * Should transfer power like any normal node. * @@ -90,7 +84,7 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(), Pow return sum / timeDiff } - lateinit var displayHandler: TextDisplayHandler + private lateinit var displayHandler: TextDisplayHandler private fun setupDisplayEntity() { displayHandler = DisplayHandlers.newBlockOverlay( @@ -119,16 +113,6 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : SingleNode(), Pow super.handlePositionRemoval(position) } - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(BlockFace::class.java), direction) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - direction = persistentDataContainer.getOrDefault(NamespacedKeys.AXIS, EnumDataType(BlockFace::class.java), NORTH) - } - private data class TransferredPower(val transferred: Int, val time: Long) override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt index 580e708612..00d497c8d9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_EXTRACTOR_NODE +import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_FLOW_METER import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_INPUT_NODE import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_INVERSE_DIRECTIONAL_NODE import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager @@ -32,7 +33,7 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory checkSolarPanels(key, 2) Material.NOTE_BLOCK -> addSimpleSingleNode(key, POWER_INPUT_NODE) - Material.OBSERVER -> addFlowMeter(data as Directional, key) + Material.OBSERVER -> addDirectionalNode(key, (data as Directional).facing, POWER_FLOW_METER) Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) @@ -46,12 +47,6 @@ class PowerNodeFactory(network: PowerNodeManager) : NodeFactory(val network: T) { @@ -57,5 +59,15 @@ abstract class NodeFactory(val network: T) { network.nodes[position] = new } + fun addDirectionalNode(position: BlockKey, direction: BlockFace, type: NodeType) { + val new = type.newInstance(network) as DirectionalNode + + new.position = position + new.direction = direction + new.onPlace(position) + + network.nodes[position] = new + } + inline fun newNode(type: NodeType): T = type.newInstance(network) as T } From 202e2377c93d932ef37ca7e83507b4e7538ad5e9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 27 Sep 2024 13:04:19 -0500 Subject: [PATCH 207/500] generalize flow meters --- ...lowMeterDisplay.kt => FlowMeterDisplay.kt} | 8 +- .../node/type/fluid/FluidNodeFactory.kt | 12 ++- .../transport/node/type/general/FlowMeter.kt | 76 ++++++++++++++++ .../node/type/power/PowerFlowMeter.kt | 88 ++----------------- 4 files changed, 95 insertions(+), 89 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/{PowerFlowMeterDisplay.kt => FlowMeterDisplay.kt} (66%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt similarity index 66% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index 15911d65d2..d809cb1220 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerFlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.client.display.modular.display -import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter import net.kyori.adventure.text.Component -class PowerFlowMeterDisplay( - private val meter: PowerFlowMeter, +class FlowMeterDisplay( + private val meter: FlowMeter, offsetLeft: Double, offsetUp: Double, offsetBack: Double, @@ -14,6 +14,6 @@ class PowerFlowMeterDisplay( override fun deRegister() {} override fun getText(): Component { - return meter.formatPower() + return meter.formatFlow() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt index 74ab5efbda..5589fe0f47 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt @@ -11,6 +11,10 @@ import net.horizonsend.ion.server.miscellaneous.utils.isChiseledCopper import net.horizonsend.ion.server.miscellaneous.utils.isCopperBlock import net.horizonsend.ion.server.miscellaneous.utils.isCopperBulb import org.bukkit.Material +import org.bukkit.Material.FLETCHING_TABLE +import org.bukkit.Material.IRON_BLOCK +import org.bukkit.Material.OBSERVER +import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional @@ -23,12 +27,12 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory addJunctionNode(key, FLUID_JUNCTION) // data.material == Material.CRAFTING_TABLE -> addSimpleSingleNode(key, FLUID_EXTRACOTR_NODE) - data.material == Material.FLETCHING_TABLE -> addSimpleSingleNode(key, FLUID_INPUT) + data.material == FLETCHING_TABLE -> addSimpleSingleNode(key, FLUID_INPUT) - data.material == Material.OBSERVER -> println("TODO") + data.material == OBSERVER -> println("TODO") - data.material == Material.REDSTONE_BLOCK -> println("TODO") - data.material == Material.IRON_BLOCK -> println("TODO") + data.material == REDSTONE_BLOCK -> println("TODO") + data.material == IRON_BLOCK -> println("TODO") // data.material == Material.LAPIS_BLOCK -> addSimpleSingleNode(key, FLUID_INVERTED_DIRECTIONAL_NODE) data.material.isChiseledCopper -> println("TODO") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt new file mode 100644 index 0000000000..90a491c6d9 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt @@ -0,0 +1,76 @@ +package net.horizonsend.ion.server.features.transport.node.type.general + +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay +import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.kyori.adventure.text.Component + +abstract class FlowMeter : DirectionalNode(), PowerPathfindingNode { + private val STORED_AVERAGES = 20 + protected val averages = mutableListOf() + + abstract fun formatFlow(): Component + + fun onCompleteChain(transferred: Int) { + addTransferred(TransferredPower(transferred, System.currentTimeMillis())) + if (::displayHandler.isInitialized) displayHandler.update() + } + + private fun addTransferred(transferredSnapshot: TransferredPower) { + val currentSize = averages.size + + if (currentSize < STORED_AVERAGES) { + averages.add(transferredSnapshot) + return + } + + // If it is full, shift all averages to the right + for (index in 18 downTo 0) { + averages[index + 1] = averages[index] + } + + averages[0] = transferredSnapshot + } + + protected fun calculateAverage(): Double { + val sum = averages.sumOf { it.transferred } + + val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 + + return sum / timeDiff + } + + private lateinit var displayHandler: TextDisplayHandler + + private fun setupDisplayEntity() { + displayHandler = DisplayHandlers.newBlockOverlay( + manager.world, + toVec3i(position), + direction, + FlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) + ).register() + } + + override fun loadIntoNetwork() { + setupDisplayEntity() + + super.loadIntoNetwork() + } + + override fun onPlace(position: BlockKey) { + runCatching { setupDisplayEntity() } + + super.onPlace(position) + } + + override fun handlePositionRemoval(position: BlockKey) { + if (::displayHandler.isInitialized) displayHandler.remove() + + super.handlePositionRemoval(position) + } + + protected data class TransferredPower(val transferred: Int, val time: Long) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt index 698a64cddb..4ae8c2604e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt @@ -3,30 +3,19 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -import net.horizonsend.ion.server.features.client.display.modular.display.PowerFlowMeterDisplay import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW -import org.bukkit.block.BlockFace -class PowerFlowMeter(override val manager: PowerNodeManager) : DirectionalNode(), PowerPathfindingNode { +class PowerFlowMeter(override val manager: PowerNodeManager) : FlowMeter(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_FLOW_METER - constructor(network: PowerNodeManager, position: BlockKey, direction: BlockFace) : this(network) { - this.position = position - this.direction = direction - } - /* * Should transfer power like any normal node. * @@ -36,20 +25,18 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : DirectionalNode() return node !is PowerExtractorNode && node !is SolarPanelNode } - private val STORED_AVERAGES = 20 - private val averages = mutableListOf() - - fun onCompleteChain(transferred: Int) { - addTransferred(TransferredPower(transferred, System.currentTimeMillis())) - if (::displayHandler.isInitialized) displayHandler.update() + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 } + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable + companion object { val firstLine = text("E: ", YELLOW) val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Second", GREEN)) } - fun formatPower(): Component { + override fun formatFlow(): Component { var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) // If no averages, or no power has been moved in 5 seconds, go to 0 @@ -59,65 +46,4 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : DirectionalNode() return ofChildren(firstLine, text(avg, GREEN), secondLine) } - - private fun addTransferred(transferredSnapshot: TransferredPower) { - val currentSize = averages.size - - if (currentSize < STORED_AVERAGES) { - averages.add(transferredSnapshot) - return - } - - // If it is full, shift all averages to the right - for (index in 18 downTo 0) { - averages[index + 1] = averages[index] - } - - averages[0] = transferredSnapshot - } - - private fun calculateAverage(): Double { - val sum = averages.sumOf { it.transferred } - - val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 - - return sum / timeDiff - } - - private lateinit var displayHandler: TextDisplayHandler - - private fun setupDisplayEntity() { - displayHandler = DisplayHandlers.newBlockOverlay( - manager.world, - toVec3i(position), - direction, - PowerFlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) - ).register() - } - - override fun loadIntoNetwork() { - setupDisplayEntity() - - super.loadIntoNetwork() - } - - override fun onPlace(position: BlockKey) { - runCatching { setupDisplayEntity() } - - super.onPlace(position) - } - - override fun handlePositionRemoval(position: BlockKey) { - if (::displayHandler.isInitialized) displayHandler.remove() - - super.handlePositionRemoval(position) - } - - private data class TransferredPower(val transferred: Int, val time: Long) - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable } From e39cb942dcb4c3d846327872dfcae08e681e06f3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 27 Sep 2024 14:07:54 -0500 Subject: [PATCH 208/500] more fluid nodes --- .../features/transport/node/NodeType.kt | 18 ++++-- .../node/type/fluid/FluidDirectionalNode.kt | 55 ++++++++++++++++++- .../node/type/fluid/FluidExtractorNode.kt | 17 +++++- .../node/type/fluid/FluidFlowMeter.kt | 24 +++++++- .../fluid/FluidInvertedDirectionalNode.kt | 32 ++++++++++- .../node/type/fluid/FluidNodeFactory.kt | 19 +++++-- .../node/type/fluid/FluidPathfindingNode.kt | 8 +++ .../node/type/general/DirectionalNode.kt | 5 ++ .../transport/node/type/general/FlowMeter.kt | 3 +- ...ode.kt => PowerInvertedDirectionalNode.kt} | 9 +-- 10 files changed, 168 insertions(+), 22 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/{InvertedDirectionalNode.kt => PowerInvertedDirectionalNode.kt} (77%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt index 8dc0406256..85bfdd71d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt @@ -2,13 +2,19 @@ package net.horizonsend.ion.server.features.transport.node import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidDirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidFlowMeter +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInvertedDirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidLinearNode import net.horizonsend.ion.server.features.transport.node.type.power.EndRodNode -import net.horizonsend.ion.server.features.transport.node.type.power.InvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInvertedDirectionalNode import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode import net.horizonsend.ion.server.features.transport.node.type.power.SpongeNode @@ -21,12 +27,16 @@ enum class NodeType(val clazz: Class) { POWER_INPUT_NODE(PowerInputNode::class.java), POWER_FLOW_METER(PowerFlowMeter::class.java), POWER_DIRECTIONAL_NODE(PowerDirectionalNode::class.java), - POWER_INVERSE_DIRECTIONAL_NODE(InvertedDirectionalNode::class.java), + POWER_INVERSE_DIRECTIONAL_NODE(PowerInvertedDirectionalNode::class.java), //FLUID - FLUID_INPUT(net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode::class.java), - FLUID_JUNCTION(net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode::class.java), + FLUID_INPUT(FluidInputNode::class.java), + FLUID_EXTRACTOR_NODE(FluidExtractorNode::class.java), + FLUID_JUNCTION(FluidJunctionNode::class.java), LIGHTNING_ROD(FluidLinearNode::class.java), + FLUID_FLOW_METER(FluidFlowMeter::class.java), + FLUID_INVERTED_DIRECTIONAL_NODE(FluidInvertedDirectionalNode::class.java), + FLUID_DIRECTIONAL_NODE(FluidDirectionalNode::class.java), //ITEM ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt index a0dd0c8a0c..2c239dc4b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt @@ -1,4 +1,57 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class FluidDirectionalNode { +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_DIRECTIONAL_NODE +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Material +import org.bukkit.persistence.PersistentDataContainer +import kotlin.properties.Delegates + +class FluidDirectionalNode(override val manager: FluidNodeManager) : DirectionalNode(), FluidPathfindingNode { + override val type: NodeType = FLUID_DIRECTIONAL_NODE + private var variant: Material by Delegates.notNull() + + constructor(network: FluidNodeManager, position: BlockKey, variant: Material) : this(network) { + this.position = position + this.variant = variant + } + + override fun isTransferableTo(node: TransportNode): Boolean { + if (node is FluidJunctionNode) return false + return node !is FluidExtractorNode + } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 + } + + override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque { + if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) + + // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. + // So there will likely only be a single relation to this + val direction = previous.getRelationshipWith(this).values + if (direction.isEmpty()) return cachedTransferable + val face = direction.first().offset + + getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } + + return cachedTransferable + } + + override fun storeData(persistentDataContainer: PersistentDataContainer) { + super.storeData(persistentDataContainer) + persistentDataContainer.set(NamespacedKeys.NODE_VARIANT, PowerDirectionalNode.materialDataType, variant) + } + + override fun loadData(persistentDataContainer: PersistentDataContainer) { + super.loadData(persistentDataContainer) + variant = persistentDataContainer.get(NamespacedKeys.NODE_VARIANT, PowerDirectionalNode.materialDataType)!! + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt index c900f1740d..8b62645d73 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt @@ -1,4 +1,19 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class FluidExtractorNode { +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_EXTRACTOR_NODE +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.SingleNode + +class FluidExtractorNode(override val manager: FluidNodeManager) : SingleNode(), FluidPathfindingNode { + override val type: NodeType = FLUID_EXTRACTOR_NODE + + override fun isTransferableTo(node: TransportNode): Boolean { + return node !is FluidExtractorNode + } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int = 0 + override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt index c486fa6022..bc4056a812 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt @@ -1,4 +1,26 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class FluidFlowMeter { +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter +import net.kyori.adventure.text.Component + +class FluidFlowMeter(override val manager: FluidNodeManager) : FlowMeter(), FluidPathfindingNode { + override val type: NodeType = NodeType.FLUID_FLOW_METER + + override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque = cachedTransferable + + override fun formatFlow(): Component { + return Component.text("bbb") + } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 0 + } + + override fun isTransferableTo(node: TransportNode): Boolean { + return true + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt index 20f6db6b60..96a22d4c26 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt @@ -1,4 +1,34 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid -class FluidInvertedDirectionalNode { +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.node.NodeType +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager +import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode + +class FluidInvertedDirectionalNode(override val manager: FluidNodeManager) : DirectionalNode(), FluidPathfindingNode { + override val type: NodeType = NodeType.FLUID_INVERTED_DIRECTIONAL_NODE + + override fun isTransferableTo(node: TransportNode): Boolean { + if (node is FluidLinearNode) return false + return node !is FluidExtractorNode + } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 1 + } + + override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque { + if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) + + // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. + // So there will likely only be a single relation to this + val direction = previous.getRelationshipWith(this).values + if (direction.isEmpty()) return cachedTransferable // just in case + val face = direction.first().offset + + getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } + + return cachedTransferable + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt index 5589fe0f47..fec691ce71 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt @@ -1,6 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_EXTRACTOR_NODE +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_FLOW_METER import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_INPUT +import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_INVERTED_DIRECTIONAL_NODE import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_JUNCTION import net.horizonsend.ion.server.features.transport.node.NodeType.LIGHTNING_ROD import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager @@ -26,14 +29,14 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory addLinearNode(key, (data as Directional).facing.axis, LIGHTNING_ROD) data.material.isCopperBlock -> addJunctionNode(key, FLUID_JUNCTION) -// data.material == Material.CRAFTING_TABLE -> addSimpleSingleNode(key, FLUID_EXTRACOTR_NODE) + data.material == Material.CRAFTING_TABLE -> addSimpleSingleNode(key, FLUID_EXTRACTOR_NODE) data.material == FLETCHING_TABLE -> addSimpleSingleNode(key, FLUID_INPUT) - data.material == OBSERVER -> println("TODO") + data.material == OBSERVER -> addDirectionalNode(key, (data as Directional).facing, FLUID_FLOW_METER) - data.material == REDSTONE_BLOCK -> println("TODO") - data.material == IRON_BLOCK -> println("TODO") -// data.material == Material.LAPIS_BLOCK -> addSimpleSingleNode(key, FLUID_INVERTED_DIRECTIONAL_NODE) + data.material == REDSTONE_BLOCK -> addMergeNode(key, REDSTONE_BLOCK) + data.material == IRON_BLOCK -> addMergeNode(key, IRON_BLOCK) + data.material == Material.LAPIS_BLOCK -> addSimpleSingleNode(key, FLUID_INVERTED_DIRECTIONAL_NODE) data.material.isChiseledCopper -> println("TODO") @@ -44,4 +47,10 @@ class FluidNodeFactory(network: FluidNodeManager) : NodeFactory +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt index 8b154f70e4..978a6b702f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.node.type.general import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.AXIS import org.bukkit.block.BlockFace @@ -23,4 +24,8 @@ abstract class DirectionalNode : SingleNode() { companion object { private val directionPDC = EnumDataType(BlockFace::class.java) } + + fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { + it.offset == incoming.oppositeFace && it.canTransfer + }?.other } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt index 90a491c6d9..4fc33a18cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt @@ -3,12 +3,11 @@ package net.horizonsend.ion.server.features.transport.node.type.general import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay -import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component -abstract class FlowMeter : DirectionalNode(), PowerPathfindingNode { +abstract class FlowMeter : DirectionalNode() { private val STORED_AVERAGES = 20 protected val averages = mutableListOf() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt similarity index 77% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt index e5cc3e22e7..f02edfedf4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/InvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt @@ -3,10 +3,9 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import org.bukkit.block.BlockFace +import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode -class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { +class PowerInvertedDirectionalNode(override val manager: PowerNodeManager) : DirectionalNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_INVERSE_DIRECTIONAL_NODE override fun isTransferableTo(node: TransportNode): Boolean { @@ -31,8 +30,4 @@ class InvertedDirectionalNode(override val manager: PowerNodeManager) : SingleNo return cachedTransferable } - - fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { - it.offset == incoming.oppositeFace && it.canTransfer - }?.other } From 83256b5f5017a97a27bd25ca2e99607c59fdedad Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 28 Sep 2024 13:24:25 -0500 Subject: [PATCH 209/500] more fluid transfer code, abstract out extractors --- .../ion/server/command/qol/SetFluidCommand.kt | 2 +- .../modular/display/fluid/FluidDisplay.kt | 6 +- .../display/fluid/SimpleFluidDisplay.kt | 2 +- .../display/fluid/SplitFluidDisplay.kt | 2 +- .../entity/type/fluids/FluidStoringEntity.kt | 30 +++---- .../type/fluids/storage/StorageContainer.kt | 9 ++- .../manager/ChunkMultiblockManager.kt | 2 +- .../multiblock/manager/MultiblockManager.kt | 2 +- .../manager/ShipMultiblockManager.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 6 +- .../features/transport/node/NodeType.kt | 2 +- .../features/transport/node/TransportNode.kt | 4 +- .../node/manager/FluidNodeManager.kt | 39 ++++++++-- .../transport/node/manager/NodeManager.kt | 4 +- .../node/manager/PowerNodeManager.kt | 8 +- .../manager/holders/ChunkNetworkHolder.kt | 2 +- .../node/manager/holders/NetworkHolder.kt | 2 +- .../node/manager/holders/ShipNetworkHolder.kt | 2 +- .../node/type/fluid/FluidDirectionalNode.kt | 9 ++- .../node/type/fluid/FluidExtractorNode.kt | 45 +++++++++-- .../node/type/fluid/FluidFlowMeter.kt | 5 ++ .../node/type/fluid/FluidInputNode.kt | 37 ++++++++- .../fluid/FluidInvertedDirectionalNode.kt | 15 ++-- .../node/type/fluid/FluidPathfindingNode.kt | 2 + .../node/type/general/ExtractorNode.kt | 30 +++++++ .../node/type/general/JunctionNode.kt | 5 +- .../transport/node/type/general/LinearNode.kt | 7 +- .../node/type/general/UnTransferableNode.kt | 4 + .../node/type/power/PowerDirectionalNode.kt | 4 +- .../node/type/power/PowerExtractorNode.kt | 78 +++---------------- .../node/type/power/PowerFlowMeter.kt | 3 +- .../power/PowerInvertedDirectionalNode.kt | 3 +- .../node/type/power/SolarPanelNode.kt | 3 +- .../transport/node/util/NodeFactory.kt | 2 +- .../features/transport/node/util/NodeUtils.kt | 20 ++--- 35 files changed, 241 insertions(+), 157 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt index ddc2fc8e04..4e5575608b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt @@ -52,7 +52,7 @@ object SetFluidCommand : SLCommand() { val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) if (entity !is FluidStoringEntity) continue - entity.getNamedStorage(storeName).storage.setContents(fluid, amount) + entity.getNamedStorage(storeName).internalStorage.setContents(fluid, amount) hits++ sender.debug("power sent") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt index 7821e8b2d5..3537e4000b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt @@ -20,15 +20,15 @@ abstract class FluidDisplay( } override fun register() { - container.storage.registerUpdateHandler(updateHandler) + container.internalStorage.registerUpdateHandler(updateHandler) } override fun deRegister() { - container.storage.removeUpdateHandler(updateHandler) + container.internalStorage.removeUpdateHandler(updateHandler) } protected fun formatFluid(): Component { - val amount = container.storage.getAmount() + val amount = container.internalStorage.getAmount() return ofChildren(text(amount, NamedTextColor.GOLD), text("L", NamedTextColor.DARK_GRAY)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index 0affcaa915..fdfd2b52d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -16,7 +16,7 @@ class SimpleFluidDisplay( scale: Float ) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { - return ofChildren(formatFluid(), space(), container.storage.getStoredFluid()?.displayName ?: empty) + return ofChildren(formatFluid(), space(), container.internalStorage.getStoredFluid()?.displayName ?: empty) } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt index f34543b5fa..65ba3449df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt @@ -14,6 +14,6 @@ class SplitFluidDisplay( scale: Float ) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { - return ofChildren(container.storage.getStoredFluid()?.displayName ?: empty, newline(), formatFluid()) + return ofChildren(container.internalStorage.getStoredFluid()?.displayName ?: empty, newline(), formatFluid()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index f03f99558e..f99e4fa8e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -21,12 +21,14 @@ interface FluidStoringEntity { /** * Returns whether any of the internal storages can store the amount of the fluid provided **/ - fun canStore(fluid: PipedFluid, amount: Int) = capacities.any { it.storage.canStore(fluid, amount) } + fun canStore(fluid: PipedFluid, amount: Int) = capacities.any { it.internalStorage.canStore(fluid, amount) } /** * Returns the first internal storage that can contain the amount of the fluid provided. **/ - fun firstCasStore(fluid: PipedFluid, amount: Int): StorageContainer? = capacities.firstOrNull { it.storage.canStore(fluid, amount) } + fun firstCasStore(fluid: PipedFluid, amount: Int): StorageContainer? = capacities.firstOrNull { it.internalStorage.canStore(fluid, amount) } + + fun isFull(): Boolean = capacities.all { it.internalStorage.isFull() } /** * Adds the amount of the fluid to the first available internal storage @@ -34,8 +36,8 @@ interface FluidStoringEntity { fun addFirstAvailable(fluid: PipedFluid, amount: Int): Int { var remaining = amount - for (container in capacities.filter { it.storage.getStoredFluid() == fluid || it.storage.getStoredFluid() == null }) { - val unfit = container.storage.addAmount(fluid, remaining) + for (container in capacities.filter { it.internalStorage.getStoredFluid() == fluid || it.internalStorage.getStoredFluid() == null }) { + val unfit = container.internalStorage.addAmount(fluid, remaining) remaining -= (remaining - unfit) if (remaining <= 0) break @@ -50,8 +52,8 @@ interface FluidStoringEntity { fun removeFirstAvailable(fluid: PipedFluid, amount: Int): Int { var remaining = amount - for (container in capacities.filter { it.storage.getStoredFluid() == fluid }) { - val unRemoved = container.storage.remove(fluid, remaining) + for (container in capacities.filter { it.internalStorage.getStoredFluid() == fluid }) { + val unRemoved = container.internalStorage.remove(fluid, remaining) remaining -= (remaining - unRemoved) if (remaining <= 0) break @@ -60,7 +62,7 @@ interface FluidStoringEntity { return remaining } - fun getStoredResources() : Map = capacities.associate { it.storage.getStoredFluid() to it.storage.getAmount() } + fun getStoredResources() : Map = capacities.associate { it.internalStorage.getStoredFluid() to it.internalStorage.getAmount() } fun getNamedStorage(name: String): StorageContainer = capacities.first { it.name == name } @@ -123,18 +125,4 @@ interface FluidStoringEntity { manager.manager.processBlockChange(world.getBlockAt(block.x, block.y, block.z)) return manager.getInternalNode(toBlockKey(block)) as? net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode } - - fun bindFluidInput() { - val existing = getFluidInputNode() ?: return - if (existing.boundMultiblockEntity != null) return - - existing.boundMultiblockEntity = this - } - - fun releaseFluidInput() { - val existing = getFluidInputNode() ?: return - if (existing.boundMultiblockEntity != this) return - - existing.boundMultiblockEntity = null - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt index cfb9faa5b7..72e600c11e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/StorageContainer.kt @@ -5,20 +5,23 @@ import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER +/** + * A wrapper around the internal storage that contains information for displaying and saving the resources. + **/ class StorageContainer( val name: String, val displayName: Component, val namespacedKey: NamespacedKey, - val storage: InternalStorage + val internalStorage: InternalStorage ) { fun save(destination: PersistentDataContainer) { val pdc = destination.adapterContext.newPersistentDataContainer() - storage.saveData(pdc) + internalStorage.saveData(pdc) destination.set(namespacedKey, TAG_CONTAINER, pdc) } override fun toString(): String { - return "Container[name= $name, key= $namespacedKey, storage= $storage]" + return "Container[name= $name, key= $namespacedKey, storage= $internalStorage]" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index c67a3c3664..7bb544133c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -40,7 +40,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag chunk.inner.minecraft.isUnsaved = true } - override fun getNetwork(type: NetworkType): NodeManager { + override fun getNetwork(type: NetworkType): NodeManager<*> { return type.get(chunk) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 1048c92a60..935cf022aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -33,7 +33,7 @@ abstract class MultiblockManager(val log: Logger) { fun getAllMultiblockEntities() = multiblockEntities - abstract fun getNetwork(type: NetworkType): NodeManager + abstract fun getNetwork(type: NetworkType): NodeManager<*> abstract fun getSignUnsavedTime(): Long open fun markSignSaved() {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 4a46d6e56d..042efa839f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -30,7 +30,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override fun getSignUnsavedTime(): Long = 0 override fun markChanged() {} - override fun getNetwork(type: NetworkType): NodeManager { + override fun getNetwork(type: NetworkType): NodeManager<*> { return type.get(starship) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 1a5930aa45..f0f41fc92a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -245,11 +245,11 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock) { //ITEM ; - fun newInstance(network: NodeManager): TransportNode { + fun newInstance(network: NodeManager<*>): TransportNode { return clazz.getDeclaredConstructor(network::class.java).newInstance(network) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt index 0c862bc4f2..0924a9bee0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt @@ -18,7 +18,7 @@ import org.bukkit.persistence.PersistentDataType **/ abstract class TransportNode : PDCSerializable { var isDead: Boolean = false - abstract val manager: NodeManager + abstract val manager: NodeManager<*> override val persistentDataType: Companion get() = Companion abstract val type: NodeType @@ -170,7 +170,7 @@ abstract class TransportNode : PDCSerializable): TransportNode = try { val type = primitive.get(NODE_TYPE, NodeType.type)!! val instance = type.newInstance(network) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index 62ea330def..271b08572c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -1,24 +1,53 @@ package net.horizonsend.ion.server.features.transport.node.manager +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidNodeFactory import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_TRANSPORT -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey -import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.Future -class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { +class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val namespacedKey: NamespacedKey = FLUID_TRANSPORT override val type: NetworkType = NetworkType.FLUID override val nodeFactory = FluidNodeFactory(this) - val extractors: ConcurrentHashMap = ConcurrentHashMap() - override val dataVersion: Int = 0 override fun clearData() { nodes.clear() extractors.clear() } + + fun tickTransport() { + extractors.values.forEach(::tickExtractor) + } + + private fun tickExtractor(extractorNode: FluidExtractorNode): Future<*> = NewTransport.executor.submit { + val check = extractorNode.getTransferAmount() + if (check == 0) return@submit + + extractorNode.markTicked() + +// val source = extractorNode.getSourcePool().filterNot { it.storage.isEmpty() }.randomOrNull() ?: return@submit +// +// val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) +// destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) +// +// if (destinations.isEmpty()) return@submit +// +// val transferred = minOf(source.storage.getPower(), check) +// val notRemoved = source.storage.removePower(transferred) +// val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) +// +// if (transferred == remainder) { +// //TODO skip growing number of ticks if nothing to do +// } +// +// if (remainder > 0) { +// source.storage.addPower(remainder) +// } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index f0f40cd674..51c15109e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.manager import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.transport.node.util.NodeFactory import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -16,8 +17,9 @@ import org.bukkit.block.data.BlockData import org.bukkit.persistence.PersistentDataContainer import java.util.concurrent.ConcurrentHashMap -abstract class NodeManager(val holder: NetworkHolder<*>) { +abstract class NodeManager(val holder: NetworkHolder<*>) { val nodes: ConcurrentHashMap = ConcurrentHashMap() + val extractors: ConcurrentHashMap = ConcurrentHashMap() val world get() = holder.getWorld() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 68bb521947..52c5fc746e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -14,19 +14,15 @@ import net.horizonsend.ion.server.features.transport.node.util.calculatePathResi import net.horizonsend.ion.server.features.transport.node.util.getIdealPath import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.NamespacedKey -import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Future import kotlin.math.roundToInt -class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { +class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER override val namespacedKey: NamespacedKey = POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) - val extractors: ConcurrentHashMap = ConcurrentHashMap() - /** Store solar panels for ticking */ val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() @@ -44,7 +40,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager(ho } fun tickExtractor(extractorNode: PowerExtractorNode): Future<*> = NewTransport.executor.submit { - val powerCheck = extractorNode.getTransferPower() + val powerCheck = extractorNode.getTransferAmount() if (powerCheck == 0) return@submit extractorNode.markTicked() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 5c5de2e4d4..7944e5f043 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -21,7 +21,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { +class ChunkNetworkHolder> private constructor (val manager: ChunkTransportManager) : NetworkHolder { override var network: T by Delegates.notNull(); private set constructor(manager: ChunkTransportManager, network: (ChunkNetworkHolder) -> T) : this(manager) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 6d55d9ac3e..328d59f4b5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World -interface NetworkHolder { +interface NetworkHolder > { val network: T val scope: CoroutineScope diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index 416e58286e..8763e30992 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World import kotlin.properties.Delegates -class ShipNetworkHolder(val manager: ShipTransportManager) : NetworkHolder { +class ShipNetworkHolder>(val manager: ShipTransportManager) : NetworkHolder { override var network: T by Delegates.notNull(); private set constructor(manager: ShipTransportManager, network: (ShipNetworkHolder) -> T) : this(manager) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt index 2c239dc4b8..d1a777ef2e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_DIRECTI import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -23,8 +24,8 @@ class FluidDirectionalNode(override val manager: FluidNodeManager) : Directional } override fun isTransferableTo(node: TransportNode): Boolean { - if (node is FluidJunctionNode) return false - return node !is FluidExtractorNode + if (node is UnTransferableNode) return false + return node !is FluidJunctionNode } override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { @@ -54,4 +55,8 @@ class FluidDirectionalNode(override val manager: FluidNodeManager) : Directional super.loadData(persistentDataContainer) variant = persistentDataContainer.get(NamespacedKeys.NODE_VARIANT, PowerDirectionalNode.materialDataType)!! } + + override fun canTransfer(resource: PipedFluid): Boolean { + return true + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt index 8b62645d73..e5ed162b3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt @@ -5,15 +5,50 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_EXTRACTOR_NODE import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.toMap -class FluidExtractorNode(override val manager: FluidNodeManager) : SingleNode(), FluidPathfindingNode { +class FluidExtractorNode(override val manager: FluidNodeManager) : ExtractorNode(), FluidPathfindingNode, UnTransferableNode { override val type: NodeType = FLUID_EXTRACTOR_NODE + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int = 0 + + override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque = cachedTransferable + override fun isTransferableTo(node: TransportNode): Boolean { - return node !is FluidExtractorNode + return node !is UnTransferableNode } - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int = 0 - override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque = cachedTransferable + override fun loadIntoNetwork() { + super.loadIntoNetwork() + manager.extractors[position] = this + } + + override fun onPlace(position: BlockKey) { + super.onPlace(position) + manager.extractors[position] = this + } + + override fun canTransfer(resource: PipedFluid): Boolean { + return false + } + + fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? FluidInputNode }.flatMap { it.getEntities() } + + fun getAvailableFluidTypes(): List { + val sources = getSourcePool() + + val new = mutableListOf() + for (source in sources) { + for ((resource, _) in source.getStoredResources()) { + new.add(resource ?: continue) + } + } + + return new + } + + fun getAvailableFluids() = getSourcePool().flatMap { it.getStoredResources().entries }.toMap() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt index bc4056a812..1e8b498509 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.kyori.adventure.text.Component class FluidFlowMeter(override val manager: FluidNodeManager) : FlowMeter(), FluidPathfindingNode { @@ -21,6 +22,10 @@ class FluidFlowMeter(override val manager: FluidNodeManager) : FlowMeter(), Flui } override fun isTransferableTo(node: TransportNode): Boolean { + return node !is UnTransferableNode + } + + override fun canTransfer(resource: PipedFluid): Boolean { return true } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt index 118413b615..b4ed85633f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt @@ -1,12 +1,22 @@ package net.horizonsend.ion.server.features.transport.node.type.fluid +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import org.bukkit.block.data.type.WallSign import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -29,9 +39,32 @@ class FluidInputNode(override val manager: FluidNodeManager) : SingleNode() { position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! } - var boundMultiblockEntity: FluidStoringEntity? = null - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 0 } + + fun getEntities(): Collection { + return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableListOf()) { + val relativeKey = getRelative(position, it) + val entity = MultiblockEntities.getMultiblockEntity(manager.world, relativeKey) as? FluidStoringEntity + if (entity != null) return@mapNotNullTo entity + + val data = getBlockDataSafe(manager.world, getX(relativeKey), getY(relativeKey), getZ(relativeKey)) ?: return@mapNotNullTo null + if (!data.material.isWallSign) return@mapNotNullTo null + data as WallSign + + val originKey = getRelative(relativeKey, data.facing.oppositeFace) + MultiblockEntities.getMultiblockEntity(manager.world, originKey) as? FluidStoringEntity + } + } + + fun canConsume(resource: PipedFluid) { + + } + + fun isCalling(): Boolean { + val entities = getEntities() + if (entities.isEmpty()) return false + return entities.any { !it.isFull() } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt index 96a22d4c26..73d7b0c36b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt @@ -5,15 +5,11 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode class FluidInvertedDirectionalNode(override val manager: FluidNodeManager) : DirectionalNode(), FluidPathfindingNode { override val type: NodeType = NodeType.FLUID_INVERTED_DIRECTIONAL_NODE - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is FluidLinearNode) return false - return node !is FluidExtractorNode - } - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { return 1 } @@ -31,4 +27,13 @@ class FluidInvertedDirectionalNode(override val manager: FluidNodeManager) : Dir return cachedTransferable } + + override fun isTransferableTo(node: TransportNode): Boolean { + if (node is UnTransferableNode) return false + return node !is FluidLinearNode + } + + override fun canTransfer(resource: PipedFluid): Boolean { + return true + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt index e29b77352f..6fca6140e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt @@ -5,4 +5,6 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode interface FluidPathfindingNode { fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque + + fun canTransfer(resource: PipedFluid): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt new file mode 100644 index 0000000000..31d6431d7f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.transport.node.type.general + +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import kotlin.math.roundToInt + +abstract class ExtractorNode : SingleNode() { + private var lastTicked: Long = System.currentTimeMillis() + + fun markTicked() { + lastTicked = System.currentTimeMillis() + } + + fun getTransferAmount(): Int { + val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() + + return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() + } + + override fun handlePositionRemoval(position: BlockKey) { + manager.extractors.remove(position) + super.handlePositionRemoval(position) + } + + override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { + return 0 + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt index 690d4c58d6..9356db1cf4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.features.transport.node.type.general import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.averageBy @@ -15,9 +14,9 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.math.roundToInt -abstract class JunctionNode, B: JunctionNode>(override val manager: T) : MultiNode() { +abstract class JunctionNode, A: JunctionNode, B: JunctionNode>(override val manager: T) : MultiNode() { override fun isTransferableTo(node: TransportNode): Boolean { - return node !is PowerExtractorNode && node !is SolarPanelNode + return node !is UnTransferableNode && node !is SolarPanelNode } override fun loadData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt index 1aae98b4a5..79a6b372c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -17,11 +16,13 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -abstract class LinearNode, B: LinearNode>(override val manager: T) : MultiNode() { +abstract class LinearNode, A: LinearNode, B: LinearNode>(override val manager: T) : MultiNode() { var axis by Delegates.notNull() override val relationOffsets: Set get() = axis.faces.toList().toSet() override fun isTransferableTo(node: TransportNode): Boolean { + if (node is UnTransferableNode) return false + // This is probably very laggy val endPoints = positions.flatMap { pos -> axis.faces.toList().map { face -> getRelative(pos, face) } @@ -32,7 +33,7 @@ abstract class LinearNode, B: LinearNode< is SingleNode -> if (!endPoints.contains(node.position)) return false } - return node !is PowerExtractorNode && node !is SolarPanelNode + return node !is SolarPanelNode } override fun loadData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt new file mode 100644 index 0000000000..38303132f6 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.transport.node.type.general + +/** Marks a node as being unable to be transferred to by any other node */ +interface UnTransferableNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt index e265ed4b77..b6a583f72b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material @@ -22,8 +23,9 @@ class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode( } override fun isTransferableTo(node: TransportNode): Boolean { + if (node is UnTransferableNode) return false if (node is SpongeNode) return false - return node !is PowerExtractorNode && node !is SolarPanelNode + return node !is SolarPanelNode } override fun storeData(persistentDataContainer: PersistentDataContainer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 48a7fba980..8d2ac05127 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -1,17 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.type.power -import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.manager.getPowerInputs -import net.horizonsend.ion.server.features.transport.node.type.SingleNode +import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import kotlin.math.roundToInt -class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { +class PowerExtractorNode(override val manager: PowerNodeManager) : ExtractorNode(), PowerPathfindingNode, UnTransferableNode { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE var tickNumber: Int = 0 @@ -29,17 +28,15 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), return node !is PowerExtractorNode && node !is SolarPanelNode } - private var lastTicked: Long = System.currentTimeMillis() + fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } - fun markTicked() { - lastTicked = System.currentTimeMillis() + override fun toString(): String { + val destinations = getPowerInputs(this) + debugAudience.highlightBlocks(destinations.map { it.getCenter() }, 30L) + return "Extractor. found, can trasnsfer: ${getTransferAmount()}, numDestinations ${destinations.size}" } - fun getTransferPower(): Int { - val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() - - return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() - } + override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable override fun loadIntoNetwork() { super.loadIntoNetwork() @@ -50,62 +47,5 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : SingleNode(), super.onPlace(position) manager.extractors[position] = this } - - override fun handlePositionRemoval(position: BlockKey) { - manager.extractors.remove(position) - super.handlePositionRemoval(position) - } - -// /** -// * Attempts to draw power from connected inputs. -// * Returns the amount that couldn't be removed. -// **/ -// fun drawPower(amount: Int): Int { -// val entities = mutableListOf() -// -// for (relation in relationships) { -// val node = relation.value.other -// if (node !is PowerInputNode) continue -// entities.addAll(node.getPoweredEntities()) -// } -// -// /* -// var remaining = amount -// -// while (remaining > 0) { -// val available = entities.filterNot { it.storage.isEmpty() } -// if (available.isEmpty()) break -// -// val minPower = entities.minOf { it.storage.getPower() } -// val idealShare = remaining / available.size -// val toRemove = minOf(idealShare, minPower) -// -// available.forEach { -// val r = it.storage.removePower(toRemove) -// remaining -= (toRemove - r) -// } -// } -// -// */ -// -// val entity = entities.randomOrNull() ?: return amount -// val remaining = entity.storage.removePower(amount) -// -// return remaining -// } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 0 - } - - fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } - - override fun toString(): String { - val destinations = getPowerInputs(this) - debugAudience.highlightBlocks(destinations.map { it.getCenter() }, 30L) - return "Extractor. found, can trasnsfer: ${getTransferPower()}, numDestinations ${destinations.size}" - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt index 4ae8c2604e..d9f8bca307 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text @@ -22,7 +23,7 @@ class PowerFlowMeter(override val manager: PowerNodeManager) : FlowMeter(), Powe * And it cannot transfer into a source */ override fun isTransferableTo(node: TransportNode): Boolean { - return node !is PowerExtractorNode && node !is SolarPanelNode + return node !is UnTransferableNode && node !is SolarPanelNode } override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt index f02edfedf4..206d407468 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt @@ -4,13 +4,14 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode class PowerInvertedDirectionalNode(override val manager: PowerNodeManager) : DirectionalNode(), PowerPathfindingNode { override val type: NodeType = NodeType.POWER_INVERSE_DIRECTIONAL_NODE override fun isTransferableTo(node: TransportNode): Boolean { if (node is EndRodNode) return false - return node !is PowerExtractorNode && node !is SolarPanelNode + return node !is UnTransferableNode && node !is SolarPanelNode } override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt index f465a68d8f..95f6785ee1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode +import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.horizonsend.ion.server.features.transport.node.util.separateNode import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS @@ -45,7 +46,7 @@ class SolarPanelNode(override val manager: PowerNodeManager) : MultiNode this.exitDistance) return false // Solar panels should be able to transfer through extractors and other solar panels - return node !is PowerExtractorNode + return node !is UnTransferableNode } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt index b23f801c11..2b6b570409 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt @@ -13,7 +13,7 @@ import org.bukkit.Axis import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData -abstract class NodeFactory(val network: T) { +abstract class NodeFactory>(val network: T) { /** * Create and handle placement of a node at the position, if one should be created **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt index 8b442276e9..fb44c4ea8d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt @@ -2,7 +2,9 @@ package net.horizonsend.ion.server.features.transport.node.util import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.node.TransportNode +import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.MultiNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -112,29 +114,29 @@ fun > separateNodePositions(node: T): List> { enum class NetworkType(val namespacedKey: NamespacedKey) { POWER(NamespacedKeys.POWER_TRANSPORT) { - override fun get(chunk: IonChunk): NodeManager { + override fun get(chunk: IonChunk): PowerNodeManager { return chunk.transportNetwork.powerNodeManager.network } - override fun get(ship: ActiveStarship): NodeManager { - TODO("Not yet implemented") + override fun get(ship: ActiveStarship): PowerNodeManager { + return ship.transportManager.powerNodeManager.network } }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { - override fun get(chunk: IonChunk): NodeManager { - return chunk.transportNetwork.powerNodeManager.network + override fun get(chunk: IonChunk): FluidNodeManager { + return chunk.transportNetwork.fluidNodeManager.network } - override fun get(ship: ActiveStarship): NodeManager { - TODO("Not yet implemented") + override fun get(ship: ActiveStarship): FluidNodeManager { + return ship.transportManager.fluidNodeManager.network } }, ; - abstract fun get(chunk: IonChunk): NodeManager - abstract fun get(ship: ActiveStarship): NodeManager + abstract fun get(chunk: IonChunk): NodeManager<*> + abstract fun get(ship: ActiveStarship): NodeManager<*> companion object { private val byKey = entries.associateBy { it.namespacedKey } From 7916f389faf786f081a5da21c39d5515a8a96fc0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 28 Sep 2024 14:21:31 -0500 Subject: [PATCH 210/500] everything but the transfer part --- .../node/manager/FluidNodeManager.kt | 26 ++++++++++++------- .../node/manager/TransportManager.kt | 1 + 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index 271b08572c..79ce39815c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -1,10 +1,14 @@ package net.horizonsend.ion.server.features.transport.node.manager +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidNodeFactory import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_TRANSPORT import org.bukkit.NamespacedKey import java.util.concurrent.Future @@ -26,19 +30,19 @@ class FluidNodeManager(holder: NetworkHolder) : NodeManager = NewTransport.executor.submit { - val check = extractorNode.getTransferAmount() - if (check == 0) return@submit + val transferCheck = extractorNode.getTransferAmount() + if (transferCheck == 0) return@submit extractorNode.markTicked() -// val source = extractorNode.getSourcePool().filterNot { it.storage.isEmpty() }.randomOrNull() ?: return@submit -// -// val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) -// destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) -// -// if (destinations.isEmpty()) return@submit -// -// val transferred = minOf(source.storage.getPower(), check) + val source = extractorNode.getSourcePool().filterNot { it.isFull() }.randomOrNull() ?: return@submit + + val destinations: ObjectOpenHashSet = getFluidInputs(extractorNode) + destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) + + if (destinations.isEmpty()) return@submit + +// val transferred = minOf(source.getPower(), check) // val notRemoved = source.storage.removePower(transferred) // val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) // @@ -51,3 +55,5 @@ class FluidNodeManager(holder: NetworkHolder) : NodeManager(origin) { it.isCalling() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt index 828bff3fc5..c7af0699ea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -8,5 +8,6 @@ abstract class TransportManager { fun tick() { powerNodeManager.network.tickTransport() + fluidNodeManager.network.tickTransport() } } From 9b14db7b1179e6fade43540be7c252e124f9e26f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 8 Oct 2024 13:12:53 -0500 Subject: [PATCH 211/500] improve multiblock ticking --- .../ticked/SyncTickingMultiblockEntity.kt | 2 +- .../ticked/TickedMultiblockEntityParent.kt | 52 ++++++++++++------- .../type/fluid/ElectrolysisMultiblock.kt | 5 +- .../collector/PipedGasCollectorMultiblock.kt | 5 +- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt index e761987345..b8358e7c28 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/SyncTickingMultiblockEntity.kt @@ -19,7 +19,7 @@ interface SyncTickingMultiblockEntity : TickedMultiblockEntityParent { if (multiblockEntity !is TickedMultiblockEntityParent) return false if (multiblockEntity.shouldCheckIntegrity() && !multiblockEntity.isIntact(false)) return false - return multiblockEntity.checkTickInterval() + return multiblockEntity.tickingManager.checkTickInterval() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt index 2516cd24ed..784f3ce64e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt @@ -1,32 +1,44 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.ticked -interface TickedMultiblockEntityParent { - val tickInterval: Int - var currentTick: Int - - var sleepTicks: Int +import com.nijiko.permissions.ModularControl.tickInterval +interface TickedMultiblockEntityParent { + val tickingManager: TickingManager + /** - * Returns true if the current tick should be allowed to proceed + * **/ - fun checkTickInterval(): Boolean { - if (sleepTicks >= 1) { - sleepTicks-- + fun shouldCheckIntegrity(): Boolean = true + + class TickingManager(val interval: Int) { + private var currentTick: Int = 0 + private var sleepTicks: Int = 0 + + /** + * Returns true if the current tick should be allowed to proceed + **/ + fun checkTickInterval(): Boolean { + if (sleepTicks >= 1) { + sleepTicks-- + + return false + } - return false + currentTick++ + if (currentTick >= tickInterval) { + currentTick = 0 + return false + } + + return true } - currentTick++ - if (currentTick >= tickInterval) { - currentTick = 0 - return false + fun sleep(ticks: Int) { + sleepTicks += ticks } - return true + fun clearSleep() { + sleepTicks = 0 + } } - - /** - * - **/ - fun shouldCheckIntegrity(): Boolean = true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index f0f41fc92a..420e6ac07c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock @@ -220,9 +221,7 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock = arrayOf( loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), From bc61eb567f631485c43980e50701a37e70b039b0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 8 Oct 2024 13:30:41 -0500 Subject: [PATCH 212/500] implement user management in multiblocks --- .../type/UserManagedMultiblockEntity.kt | 47 +++++++++++++++++++ .../persistence/NamespacedKeys.kt | 1 + 2 files changed, 48 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt new file mode 100644 index 0000000000..697df9ca62 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt @@ -0,0 +1,47 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import com.manya.pdc.base.UuidDataType +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.Bukkit.getPlayer +import org.bukkit.entity.Player +import org.bukkit.persistence.PersistentDataType.STRING +import java.util.UUID + +interface UserManagedMultiblockEntity { + val userManager: UserManager + + /** + * Holds information about who is currently using this multiblock. + **/ + class UserManager(data: PersistentMultiblockData, private val persistent: Boolean) { + private var user: UUID? = data.getAdditionalData(NamespacedKeys.DRILL_USER, UuidDataType()) + private var userName: String? = data.getAdditionalData(NamespacedKeys.DRILL_USER_NAME, STRING) + + fun clear() { + user = null + userName = null + } + + fun setUser(player: Player) { + user = player.uniqueId + userName = player.name + } + + /** + * + **/ + fun currentlyUsed() = (user != null) + + /** + * Gets the player of the user, if there is one + **/ + fun getUserPlayer(): Player? = user?.let(::getPlayer) + + fun saveUserData(store: PersistentMultiblockData) { + if (!persistent) return + user?.let { store.addAdditionalData(NamespacedKeys.DRILL_USER, UuidDataType(), it) } + userName?.let { store.addAdditionalData(NamespacedKeys.DRILL_USER_NAME, STRING, it) } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 3e65d7c714..27f05bd8d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -52,6 +52,7 @@ object NamespacedKeys { val SPLITTER_DIRECTION = key("splitter_direction") val DRILL_USER = key("drill_user") + val DRILL_USER_NAME = key("drill_user_name") @Deprecated("") val ORE_CHECK = key("oreCheck") From 7954f1ec4047626418f7f0c08a260bfa14be4024 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 8 Oct 2024 14:33:29 -0500 Subject: [PATCH 213/500] migrate drills --- .../command/starship/MiscStarshipCommands.kt | 18 +- .../multiblock/MultiblockRegistration.kt | 7 + .../type/UserManagedMultiblockEntity.kt | 2 + .../features/multiblock/old/Multiblocks.kt | 7 - .../multiblock/type/drills/DrillMultiblock.kt | 388 +++++++++--------- .../subsystem/misc/MiningLaserSubsystem.kt | 1 - 6 files changed, 206 insertions(+), 217 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index 00f0cebce9..57254ab385 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -36,7 +36,6 @@ import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.client.display.HudIcons import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic -import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.space.Space @@ -80,7 +79,6 @@ import net.kyori.adventure.text.format.NamedTextColor.WHITE import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.World -import org.bukkit.block.Sign import org.bukkit.entity.Enemy import org.bukkit.entity.EntityType import org.bukkit.entity.Player @@ -89,7 +87,6 @@ import java.util.Locale import java.util.UUID import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.TimeUnit -import kotlin.collections.set import kotlin.math.PI import kotlin.math.abs import kotlin.math.atan2 @@ -693,16 +690,13 @@ object MiscStarshipCommands : net.horizonsend.ion.server.command.SLCommand() { fun onToggleDrills(sender: Player, enabled: Boolean) { val starship = getStarshipPiloting(sender) - val signs = starship.drills.mapNotNull { - val (x, y, z) = it.pos - - starship.world.getBlockAt(x, y, z).state as? Sign - } - - val user = if (enabled) sender.name else null + val entities = starship.multiblockManager.getAllMultiblockEntities().values.filterIsInstance() - for (sign in signs) { - DrillMultiblock.setUser(sign, user) + for (entity in entities) { + if (enabled) { + val sign = entity.getSign() ?: continue + entity.enable(sender, sign) + } else entity.disable() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 8a0ae5413d..9c2721ac82 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -11,6 +11,9 @@ import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areas import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield5 import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium @@ -115,6 +118,10 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(ChargerMultiblockTier2) registerMultiblock(ChargerMultiblockTier3) + registerMultiblock(DrillMultiblockTier1) + registerMultiblock(DrillMultiblockTier2) + registerMultiblock(DrillMultiblockTier3) + // Gas registerMultiblock(PipedGasCollectorMultiblock) registerMultiblock(ElectrolysisMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt index 697df9ca62..f02810fad4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt @@ -38,6 +38,8 @@ interface UserManagedMultiblockEntity { **/ fun getUserPlayer(): Player? = user?.let(::getPlayer) + fun getUserId(): UUID? = user + fun saveUserData(store: PersistentMultiblockData) { if (!persistent) return user?.let { store.addAdditionalData(NamespacedKeys.DRILL_USER, UuidDataType(), it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index b08a408afd..ccb0730c19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -18,9 +18,6 @@ import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCraft import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock -import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier3 @@ -113,10 +110,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(GlassPrinterMultiblock) registerMultiblock(ArmorPrinterMultiblock) - registerMultiblock(DrillMultiblockTier1) - registerMultiblock(DrillMultiblockTier2) - registerMultiblock(DrillMultiblockTier3) - registerMultiblock(StandardGravityWellMultiblock) registerMultiblock(AmplifiedGravityWellMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index f8ca106ebc..9e4d5a12a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -5,131 +5,49 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.extensions.userErrorAction import net.horizonsend.ion.common.extensions.userErrorSubtitle import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity.UserManager +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DRILL_USER import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox -import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.RED -import org.bukkit.Bukkit import org.bukkit.Material +import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.BlockFace import org.bukkit.block.BlockFace.UP -import org.bukkit.block.Furnace import org.bukkit.block.Sign -import org.bukkit.block.sign.Side import org.bukkit.entity.Player import org.bukkit.event.block.Action import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.inventory.FurnaceBurnEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder -import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataAdapterContext import java.util.EnumSet import java.util.UUID import kotlin.math.max -abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : - Multiblock(), - PowerStoringMultiblock, - FurnaceMultiblock, - InteractableMultiblock { - - companion object { - private val DISABLED = text("[DISABLED]", RED) - private val blacklist = EnumSet.of( - Material.BARRIER, - Material.BEDROCK, - Material.VOID_AIR - ) - - private var lastDrillCount: Map = mutableMapOf() - private var drillCount: MutableMap = mutableMapOf() - - init { - // TODO: do something less stupid for this - Tasks.syncRepeat(delay = 1, interval = 1) { - lastDrillCount = drillCount - drillCount = mutableMapOf() - } - } - - fun isEnabled(sign: Sign): Boolean { - return sign.getSide(Side.FRONT).line(3) != DISABLED - } - - fun setUser(sign: Sign, player: String?) { - sign.getSide(Side.FRONT).line(3, player?.let { text(it) } ?: DISABLED) - - if (player == null) sign.persistentDataContainer.remove(DRILL_USER) else sign.persistentDataContainer.set(DRILL_USER, PersistentDataType.STRING, player) - - sign.update(false, false) - } - - fun isBlacklisted(block: Block): Boolean { - return blacklist.contains(block.type) - } - - - fun breakBlocks( - sign: Sign, - maxBroken: Int, - toDestroy: MutableList, - output: Inventory, - canBuild: (Block) -> Boolean, - cancel: (Sign) -> Unit - ): Int { - var broken = 0 - - for (block in toDestroy) { - if (isBlacklisted(block)) { - continue - } - - val customBlock = CustomBlocks.getByBlock(block) - var drops = customBlock?.drops?.getDrops(null, false) ?: if (block.type == Material.SNOW_BLOCK) listOf() else block.drops - - if (block.type.isShulkerBox) drops = listOf() - - if (!canBuild(block)) { - continue - } - - for (item in drops) { - if (!LegacyItemUtils.canFit(output, item)) { - cancel(sign) - - return broken - } - - LegacyItemUtils.addToInventory(output, item) - } - - val applyPhysics = block.type == Material.COBBLESTONE - block.setType(Material.AIR, applyPhysics) - - broken++ - if (broken >= maxBroken) { - break - } - } - return broken - } - } - +abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { abstract val radius: Int abstract val coolDown: Int @@ -145,28 +63,9 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : line4 = null ) - fun getOutput(sign: Block): Inventory { - val direction = (sign.getState(false) as Sign).getFacing().oppositeFace - return if (!mirrored) { - (sign.getRelative(direction) - .getRelative(direction.leftFace) - .getState(false) as InventoryHolder - ) - .inventory - } else { - (sign.getRelative(direction) - .getRelative(direction.rightFace) - .getState(false) as InventoryHolder - ) - .inventory - } - } - override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { if (event.action != Action.RIGHT_CLICK_BLOCK) return - - val furnace = event.clickedBlock!!.getRelative(sign.getFacing().oppositeFace).getState(false) as? Furnace - ?: return + val entity = getMultiblockEntity(sign) ?: return if (furnace.inventory.let { it.fuel == null || it.smelting?.type != Material.PRISMARINE_CRYSTALS }) { event.player.userErrorAction( @@ -175,11 +74,6 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : return } - if (CombatTimer.isPvpCombatTagged(player)) { - player.userError("Cannot enable drills while in combat") - return - } - val user = when { isEnabled(sign) -> null else -> event.player.name @@ -230,108 +124,208 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : } override fun onTransformSign(player: Player, sign: Sign) { - sign.getSide(Side.FRONT).line(3, DISABLED) + sign.front().line(3, DISABLED) } - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isBurning = false - event.burnTime = 0 + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): DrillMultiblockEntity { + return DrillMultiblockEntity(data, manager, this, x, y, z, world, structureDirection) + } + + class DrillMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: DrillMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickingManager = TickingManager(interval = 5) + override val userManager: UserManager = UserManager(data, persistent = true) + + override fun tick() { + val player = userManager.getUserPlayer() ?: return disable() + + if (CombatTimer.isPvpCombatTagged(player)) { + player.userError("Cannot enable drills while in combat") + return + } + + /* + if (SpaceWorlds.contains(furnace.world) && !furnace.world.name.contains("plots", ignoreCase = true)) { + player.userError("Starship drills are not optimized for use in outer space! The starship drill was not enabled.") + setUser(sign, null) + return + } + */ - val fuel = furnace.inventory.fuel - val smelting = furnace.inventory.smelting - if (fuel == null || smelting == null) return + drillCount[player.uniqueId] = drillCount.getOrDefault(player.uniqueId, 0) + 1 + val drills = lastDrillCount.getOrDefault(player.uniqueId, 1) - val pdcUser = sign.persistentDataContainer.get(DRILL_USER, PersistentDataType.STRING) ?: return - val player = Bukkit.getPlayer(pdcUser) + if (drills > 16) return player.userErrorAction("You cannot use more than 16 drills at once!") + if (!isEnabled()) return - if (player == null) { - setUser(sign, null) - return - } + val power = storage.getPower() + if (power == 0) { + disable() + return player.alertSubtitle("Your drill at $vec3i ran out of power! It was disabled.") + } - /* - if (SpaceWorlds.contains(furnace.world) && !furnace.world.name.contains("plots", ignoreCase = true)) { - player.userError("Starship drills are not optimized for use in outer space! The starship drill was not enabled.") - setUser(sign, null) - return + val inSpace = world.ion.hasFlag(WorldFlag.SPACE_WORLD) + if (inSpace) tickingManager.sleep(15) + + val toDestroy = getBlocksToDestroy() + + // set to 1 block broken per furnace tick in space + val maxBroken = if (!inSpace) { + max(1, if (drills > 5) (5 + drills) / drills + 15 / drills else 10 - drills) + } else 1 + + val broken = breakBlocks( + maxBroken, + toDestroy, + getOutput(), + { + val testEvent = BlockBreakEvent(it, player) + testEvent.isDropItems = false + + return@breakBlocks testEvent.callEvent() + }, + { + player.userErrorSubtitle("Not enough space.") + disable() + } + ) + + val powerUsage = broken * 50 + storage.setPower(power - powerUsage) } - */ - drillCount[player.uniqueId] = drillCount.getOrDefault(player.uniqueId, 0) + 1 - val drills = lastDrillCount.getOrDefault(player.uniqueId, 1) + fun handleClick(sign: Sign, player: Player) { + val previousUser = userManager.getUserId() + if (previousUser == null) { + // Toggle on + enable(player, sign) + return + } - if (drills > 16) { - player.userErrorAction("You cannot use more than 16 drills at once!") - return + // Toggle off + disable() } - if (!isEnabled(sign) || smelting.type != Material.PRISMARINE_CRYSTALS) { - return + fun enable(player: Player, sign: Sign) { + userManager.setUser(player) + sign.front().line(3, text(player.name)) + sign.update(false, false) } - event.isCancelled = true - val power = PowerMachines.getPower(sign, true) - if (power == 0) { - setUser(sign, null) - player.alertSubtitle("Your drill at ${sign.location.toVector()} ran out of power! It was disabled.") - return + fun disable() { + val sign = getSign() ?: return + + userManager.clear() + sign.front().line(3, empty()) + sign.update(false, false) } - val inSpace = furnace.world.ion.hasFlag(WorldFlag.SPACE_WORLD) + private fun isEnabled(): Boolean { + return userManager.currentlyUsed() + } - event.isBurning = false - event.burnTime = if (!inSpace) 5 else 20 - furnace.cookTime = (-1000).toShort() - event.isCancelled = false + private fun getBlocksToDestroy(): MutableList { + val center = getBlockRelative(4, 0, 0) + val right = structureDirection.rightFace - val toDestroy = getBlocksToDestroy(sign) + val toDestroy = mutableListOf() - // set to 1 block broken per furnace tick in space - val maxBroken = if (!inSpace) { - max(1, if (drills > 5) (5 + drills) / drills + 15 / drills else 10 - drills) - } else 1 + for (h in -multiblock.radius..multiblock.radius) { + for (v in -multiblock.radius..multiblock.radius) { + val block = center.getRelative(right, h).getRelative(UP, v) + if (block.type == Material.AIR) continue + if (block.type == Material.BEDROCK) continue + toDestroy.add(block) + } + } - val broken = breakBlocks( - sign, - maxBroken, - toDestroy, - getOutput(sign.block), - { - val testEvent = BlockBreakEvent(it, player) - testEvent.isDropItems = false + toDestroy.sortBy { it.location.distanceSquared(center.location) } - return@breakBlocks testEvent.callEvent() - }, - { - player.userErrorSubtitle("Not enough space.") + return toDestroy + } - setUser(sign, null) - } - ) + fun getOutput(): Inventory { + return (getBlockRelative(0, -1, 0).getState(false) as InventoryHolder).inventory + } - val powerUsage = broken * 50 - PowerMachines.setPower(sign, power - powerUsage, true) - } + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + userManager.saveUserData(store) + savePowerData(store) + } - private fun getBlocksToDestroy(sign: Sign): MutableList { - val direction = sign.getFacing().oppositeFace + override val powerInputOffset: Vec3i = Vec3i(0, 0, 0) + } - val right = direction.rightFace - val center = sign.block.getRelative(direction, 5) + companion object { + private val DISABLED = text("[DISABLED]", RED) + private val blacklist = EnumSet.of( + Material.BARRIER, + Material.BEDROCK, + Material.VOID_AIR + ) - val toDestroy = mutableListOf() + private var lastDrillCount: Map = mutableMapOf() + private var drillCount: MutableMap = mutableMapOf() - for (h in -this.radius..this.radius) { - for (v in -this.radius..this.radius) { - val block = center.getRelative(right, h).getRelative(UP, v) - if (block.type == Material.AIR) continue - if (block.type == Material.BEDROCK) continue - toDestroy.add(block) + init { + // TODO: do something less stupid for this + Tasks.syncRepeat(delay = 1, interval = 1) { + lastDrillCount = drillCount + drillCount = mutableMapOf() } } - toDestroy.sortBy { it.location.distanceSquared(center.location) } + fun isBlacklisted(block: Block): Boolean { + return blacklist.contains(block.type) + } - return toDestroy + fun breakBlocks( + maxBroken: Int, + toDestroy: MutableList, + output: Inventory, + canBuild: (Block) -> Boolean, + cancel: () -> Unit + ): Int { + var broken = 0 + + for (block in toDestroy) { + if (isBlacklisted(block)) { + continue + } + + val customBlock = CustomBlocks.getByBlock(block) + var drops = customBlock?.drops?.getDrops(null, false) ?: if (block.type == Material.SNOW_BLOCK) listOf() else block.drops + + if (block.type.isShulkerBox) drops = listOf() + + if (!canBuild(block)) { + continue + } + + for (item in drops) { + if (!LegacyItemUtils.canFit(output, item)) return broken + + LegacyItemUtils.addToInventory(output, item) + } + + val applyPhysics = block.type == Material.COBBLESTONE + block.setType(Material.AIR, applyPhysics) + + broken++ + if (broken >= maxBroken) { + break + } + } + return broken + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt index da7b0eb0e4..afc4923da4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt @@ -269,7 +269,6 @@ class MiningLaserSubsystem( } val blocksBroken = DrillMultiblock.breakBlocks( - sign = sign, maxBroken = multiblock.maxBroken, toDestroy = blocks, output = multiblock.getOutput(sign), From 17cdcf1c5874486d14de8a798b434d6d6902aea8 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 8 Oct 2024 20:57:52 -0500 Subject: [PATCH 214/500] add more multiblock utils --- .../multiblock/entity/MultiblockEntity.kt | 6 ++++++ .../multiblock/type/drills/DrillMultiblock.kt | 19 +++++-------------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 9a72f47f29..4aa7fafb81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -16,6 +16,8 @@ import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.InventoryHolder import org.bukkit.persistence.PersistentDataAdapterContext /** @@ -157,6 +159,10 @@ abstract class MultiblockEntity( return world.getBlockAt(x, y, z) } + fun getInventory(backFourth: Int, leftRight: Int, upDown: Int): Inventory? { + return (getBlockRelative(backFourth, leftRight, upDown).getState(false) as? InventoryHolder)?.inventory + } + fun displace(movement: StarshipMovement) { val newX = movement.displaceX(x, z) val newY = movement.displaceY(y) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 9e4d5a12a3..9a282cbc20 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -67,19 +67,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M if (event.action != Action.RIGHT_CLICK_BLOCK) return val entity = getMultiblockEntity(sign) ?: return - if (furnace.inventory.let { it.fuel == null || it.smelting?.type != Material.PRISMARINE_CRYSTALS }) { - event.player.userErrorAction( - "You need Prismarine Crystals in both slots of the furnace!" - ) - return - } - - val user = when { - isEnabled(sign) -> null - else -> event.player.name - } - - setUser(sign, user) + entity.handleClick(sign, player) } override fun MultiblockShape.buildStructure() { @@ -186,7 +174,10 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M val broken = breakBlocks( maxBroken, toDestroy, - getOutput(), + getInventory(0, -1, 0) ?: return run { + player.userError("Drill output inventory destroyed") + disable() + }, { val testEvent = BlockBreakEvent(it, player) testEvent.isDropItems = false From 1f397bc8a18f70c9ad3ee2f3f6b5663cc6d68400 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 14:53:19 -0500 Subject: [PATCH 215/500] entity subsystem, migrate mining lasers, migrate entities on pilot --- .../command/starship/StarshipDebugCommand.kt | 34 +++ .../features/multiblock/MultiblockEntities.kt | 2 +- .../multiblock/MultiblockRegistration.kt | 28 +++ .../multiblock/entity/MultiblockEntity.kt | 4 + .../type/power/PoweredMultiblockEntity.kt | 16 -- .../manager/ShipMultiblockManager.kt | 41 ++++ .../features/multiblock/old/Multiblocks.kt | 27 --- .../multiblock/type/EntityMultiblock.kt | 7 +- .../defense/passive/areashield/AreaShield.kt | 3 +- .../multiblock/type/drills/DrillMultiblock.kt | 33 ++- .../type/fluid/ElectrolysisMultiblock.kt | 4 +- .../type/power/charger/ChargerMultiblock.kt | 5 +- .../type/power/storage/PowerBankMultiblock.kt | 5 +- .../type/power/storage/PowerCellMultiblock.kt | 2 - .../mininglasers/MiningLaserMultiblock.kt | 100 ++++++--- .../MiningLaserMultiblockTier1.kt | 9 +- .../MiningLaserMultiblockTier2.kt | 9 +- .../MiningLaserMultiblockTier3.kt | 9 +- .../MiningLaserMultiblockTier4.kt | 9 +- .../starship/active/SubsystemDetector.kt | 10 +- .../subsystem/MultiblockEntitySubsystem.kt | 7 + .../subsystem/misc/MiningLaserSubsystem.kt | 207 +++++++----------- 22 files changed, 328 insertions(+), 243 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/MultiblockEntitySubsystem.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt index 24c7a12d5d..1c681cb43e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt @@ -3,13 +3,16 @@ package net.horizonsend.ion.server.command.starship import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission +import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.ai.module.targeting.TargetingModule +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships import net.horizonsend.ion.server.features.starship.active.ActiveStarships @@ -24,6 +27,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile. import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.helixAroundVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.Location import org.bukkit.Particle @@ -227,4 +232,33 @@ object StarshipDebugCommand : SLCommand() { abstract fun apply(controller: ActivePlayerController) } + + @Subcommand("dumpEntities") + fun onDumpEntities(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { + val manager = getStarshipRiding(sender).multiblockManager + val entities = manager.getAllMultiblockEntities().toList() + + sender.sendMessage(formatPaginatedMenu( + entities.size, + "/ionchunk dumpentities ${visual ?: false}", + page ?: 1, + ) { index -> + val (key, entity) = entities[index] + + val vec = toVec3i(key) + + Component.text("$vec : $entity") + }) + + if (visual == true) { + for ((key, _) in entities) { + val vec = toVec3i(key) + + sender.highlightBlock(vec, 30L) + } + } + + sender.information("Sync Ticked: ${manager.syncTickingMultiblockEntities}") + sender.information("Async Ticked: ${manager.asyncTickingMultiblockEntities}") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 35a6ac0b59..aa7a596942 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -104,7 +104,7 @@ object MultiblockEntities : SLEventListener() { } } - private fun migrateFromSign(sign: Sign, type: EntityMultiblock<*>) { + fun migrateFromSign(sign: Sign, type: EntityMultiblock<*>) { val origin = MultiblockEntity.getOriginFromSign(sign) val ionChunk = getIonChunk(sign.world, origin.x, origin.z) ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 9c2721ac82..5ffd71b19a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -2,9 +2,13 @@ package net.horizonsend.ion.server.features.multiblock import com.google.common.collect.Multimap import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Bottom +import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Side +import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Top import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop +import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield10 import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield20 import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield30 @@ -51,6 +55,15 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.H import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass2 import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass3 import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass4 +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Top import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblockBasic import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced @@ -122,6 +135,19 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(DrillMultiblockTier2) registerMultiblock(DrillMultiblockTier3) + registerMultiblock(MiningLaserMultiblockTier1Top) + registerMultiblock(MiningLaserMultiblockTier1Bottom) + registerMultiblock(MiningLaserMultiblockTier1Side) + registerMultiblock(MiningLaserMultiblockTier2Top) + registerMultiblock(MiningLaserMultiblockTier2Bottom) + registerMultiblock(MiningLaserMultiblockTier2Side) + registerMultiblock(MiningLaserMultiblockTier3Top) + registerMultiblock(MiningLaserMultiblockTier3Bottom) + registerMultiblock(MiningLaserMultiblockTier3Side) + registerMultiblock(MiningLaserMultiblockTier4Top) + registerMultiblock(MiningLaserMultiblockTier4Bottom) + registerMultiblock(MiningLaserMultiblockTier4Side) + // Gas registerMultiblock(PipedGasCollectorMultiblock) registerMultiblock(ElectrolysisMultiblock) @@ -217,6 +243,8 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(AirlockMultiblock) registerMultiblock(ExpandableAirlock) registerMultiblock(TractorBeamMultiblock) + + registerMultiblock(AntiAirCannonBaseMultiblock) } private fun sortMultiblocks() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 4aa7fafb81..1fa66b918c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -159,6 +159,10 @@ abstract class MultiblockEntity( return world.getBlockAt(x, y, z) } + fun getPosRelative(backFourth: Int, leftRight: Int, upDown: Int): Vec3i { + return getRelative(vec3i, structureDirection, backFourth, leftRight, upDown) + } + fun getInventory(backFourth: Int, leftRight: Int, upDown: Int): Inventory? { return (getBlockRelative(backFourth, leftRight, upDown).getState(false) as? InventoryHolder)?.inventory } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index f13929264e..d197a410d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,11 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { @@ -19,17 +16,4 @@ interface PoweredMultiblockEntity { fun savePowerData(store: PersistentMultiblockData) { store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, storage.getPower()) } - - val powerInputOffset: Vec3i - - fun getRealInputLocation(): Vec3i { - this as MultiblockEntity - return getRelative( - origin = vec3i, - forwardFace= structureDirection, - right = powerInputOffset.x, - up = powerInputOffset.y, - forward = powerInputOffset.z - ) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 042efa839f..7273b8ca00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -1,20 +1,30 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import org.bukkit.block.Sign import java.util.concurrent.ConcurrentHashMap class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServer.slF4JLogger) { @@ -37,6 +47,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe init { loadEntities() MultiblockTicking.registerMultiblockManager(this) + tryFixEntities() } fun loadEntities() { @@ -66,6 +77,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe fun release() { MultiblockTicking.removeMultiblockManager(this) + releaseEntities() } fun releaseEntities() { @@ -149,4 +161,33 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe asyncTickingMultiblockEntities = newAsyncTicking } + + /** Mostly to be used with blueprint load or loadship, loads entities from their sign data */ + private fun tryFixEntities() { + starship.iterateBlocks { x, y, z -> + if (isOccupied(x, y, z)) return@iterateBlocks + + val type = getBlockTypeSafe(world, x, y, z) + if (type?.isWallSign != true) return@iterateBlocks + + val state = world.getBlockState(x, y, z) as? Sign ?: return@iterateBlocks + val multiblock = MultiblockAccess.getFast(state) + if (multiblock !is EntityMultiblock<*>) return@iterateBlocks + + val data = state.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return MultiblockEntities.migrateFromSign(state, multiblock) + + val origin = MultiblockEntity.getOriginFromSign(state) + + // In case it moved + data.x = origin.x + data.y = origin.y + data.z = origin.z + data.signOffset = state.getFacing().oppositeFace + + val new = MultiblockEntities.loadFromData(multiblock, this, data) + if (new is LegacyMultiblockEntity) new.loadFromSign(state) + + addMultiblockEntity(new) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index ccb0730c19..9a63b501ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -8,16 +8,12 @@ import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.command.misc.MultiblockCommand.setupCommand import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockAccess.multiblockCoroutineScope -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Bottom -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Side -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Top import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier3 @@ -49,15 +45,6 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterM import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.AmplifiedGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.StandardGravityWellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Bottom -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Side -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Top -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Bottom -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Side -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Top -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Bottom -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Side -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Top import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement @@ -119,18 +106,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(DecomposerMultiblock) registerMultiblock(DisposalMultiblock) - registerMultiblock(MiningLaserMultiblockTier1Top) - registerMultiblock(MiningLaserMultiblockTier1Bottom) - registerMultiblock(MiningLaserMultiblockTier1Side) - registerMultiblock(MiningLaserMultiblockTier2Top) - registerMultiblock(MiningLaserMultiblockTier2Bottom) - registerMultiblock(MiningLaserMultiblockTier2Side) - registerMultiblock(MiningLaserMultiblockTier3Top) - registerMultiblock(MiningLaserMultiblockTier3Bottom) - registerMultiblock(MiningLaserMultiblockTier3Side) - registerMultiblock(MiningLaserMultiblockTier4Top) - registerMultiblock(MiningLaserMultiblockTier4Bottom) - registerMultiblock(MiningLaserMultiblockTier4Side) registerMultiblock(ItemSplitterMultiblock) registerMultiblock(GasCollectorMultiblock) @@ -147,8 +122,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(HarvesterMultiblockTier1) registerMultiblock(HarvesterMultiblockTier2) registerMultiblock(HarvesterMultiblockTier3) - - registerMultiblock(AntiAirCannonBaseMultiblock) } private fun registerMultiblock(multiblock: Multiblock) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt index ebf78b7a1c..eab3cca160 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/EntityMultiblock.kt @@ -37,15 +37,16 @@ interface EntityMultiblock { return world.ion.getChunk(chunkX, chunkZ)?.multiblockManager?.get(x, y, z) as T? } - fun getMultiblockEntity(sign: Sign): T? { + fun getMultiblockEntity(sign: Sign, ignoreShips: Boolean = false): T? { val origin = MultiblockEntity.getOriginFromSign(sign) val world = sign.world val ship = ActiveStarships.getInWorld(world).firstOrNull { it.contains(origin.x, origin.y, origin.z) } - if (ship != null) { + if (ship != null && !ignoreShips) { @Suppress("UNCHECKED_CAST") - return ship.multiblockManager[origin.x, origin.y, origin.z] as T? + val multi = ship.multiblockManager[origin.x, origin.y, origin.z] as T? + if (multi != null) return multi } @Suppress("UNCHECKED_CAST") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 53961e8a5e..b11ebae322 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -131,6 +131,5 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< savePowerData(store) } - override val powerInputOffset: Vec3i = Vec3i(0, -1, 0) - } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 9a282cbc20..75c7e840b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -4,6 +4,8 @@ import net.horizonsend.ion.common.extensions.alertSubtitle import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.extensions.userErrorAction import net.horizonsend.ion.common.extensions.userErrorSubtitle +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity @@ -19,11 +21,11 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.player.CombatTimer +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.horizonsend.ion.server.miscellaneous.utils.rightFace @@ -141,14 +143,6 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M return } - /* - if (SpaceWorlds.contains(furnace.world) && !furnace.world.name.contains("plots", ignoreCase = true)) { - player.userError("Starship drills are not optimized for use in outer space! The starship drill was not enabled.") - setUser(sign, null) - return - } - */ - drillCount[player.uniqueId] = drillCount.getOrDefault(player.uniqueId, 0) + 1 val drills = lastDrillCount.getOrDefault(player.uniqueId, 1) @@ -253,7 +247,26 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M savePowerData(store) } - override val powerInputOffset: Vec3i = Vec3i(0, 0, 0) + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 420e6ac07c..4f4d17794a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -274,9 +274,7 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, PowerStoringMultiblock { +abstract class MiningLaserMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "mininglaser" abstract val range: Double @@ -28,31 +29,64 @@ abstract class MiningLaserMultiblock : Multiblock(), SubsystemMultiblock { starship.subsystems += GravityWellSubsystem(starship, sign, multiblock) } + + is MiningLaserMultiblock -> { + // Multiblocks are loaded onto ships before his step + val entity = starship.multiblockManager[sign] as? MiningLaserMultiblock.MiningLaserMultiblockEntity ?: return + starship.subsystems += MiningLaserSubsystem(starship, entity) + } } } private fun detectThruster(starship: ActiveControlledStarship, block: Block) { for (face in CARDINAL_BLOCK_FACES) { - val thrusterType: ThrusterType = ThrusterType.values() + val thrusterType: ThrusterType = ThrusterType.entries .firstOrNull { it.matchesStructure(starship, block.x, block.y, block.z, face) } ?: continue val pos = Vec3i(block.blockKey) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/MultiblockEntitySubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/MultiblockEntitySubsystem.kt new file mode 100644 index 0000000000..ed8a386d13 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/MultiblockEntitySubsystem.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.starship.subsystem + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity + +interface MultiblockEntitySubsystem { + val entity: MultiblockEntity +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt index afc4923da4..ede2bd6552 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt @@ -1,14 +1,15 @@ package net.horizonsend.ion.server.features.starship.subsystem.misc import fr.skytasul.guardianbeam.Laser.CrystalLaser +import net.horizonsend.ion.common.extensions.alert import net.horizonsend.ion.common.extensions.alertSubtitle import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.informationAction +import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.extensions.userErrorSubtitle import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.machine.AreaShields -import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship @@ -16,13 +17,12 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.event.build.StarshipBreakBlockEvent import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem +import net.horizonsend.ion.server.features.starship.subsystem.MultiblockEntitySubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.enumSetOf -import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.horizonsend.ion.server.miscellaneous.utils.runnable import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -33,16 +33,17 @@ import org.bukkit.Particle import org.bukkit.SoundCategory import org.bukkit.block.Block import org.bukkit.block.BlockFace -import org.bukkit.block.Sign import org.bukkit.scheduler.BukkitTask import org.bukkit.util.Vector class MiningLaserSubsystem( override val starship: ActiveControlledStarship, - pos: Vec3i, - override var face: BlockFace, - val multiblock: MiningLaserMultiblock, -) : WeaponSubsystem(starship, pos), ManualWeaponSubsystem, DirectionalSubsystem { + override val entity: MiningLaserMultiblock.MiningLaserMultiblockEntity, +) : WeaponSubsystem(starship, entity.vec3i), ManualWeaponSubsystem, DirectionalSubsystem, MultiblockEntitySubsystem { + + val multiblock = entity.multiblock + override var face: BlockFace = entity.structureDirection + override val balancing: StarshipWeapons.StarshipWeapon = StarshipWeapons.StarshipWeapon( range = 0.0, speed = 0.0, @@ -69,53 +70,32 @@ class MiningLaserSubsystem( private var isFiring = false lateinit var targetedBlock: Vector - // Starship power usage, 0 - override val powerUsage: Int = 0 - // Power used per block broken private val blockBreakPowerUsage: Double = 9.0 - // Save some calc time private val radiusSquared = multiblock.mineRadius * multiblock.mineRadius - var tick = 0 - override fun getAdjustedDir(dir: Vector, target: Vector): Vector { - val firePos = getFirePos() + val firePos = entity.getFirePos() val vector = target.clone().subtract(firePos.toVector()) return firePos.toVector().add(vector.clone().normalize().multiply(multiblock.range)) } override fun canFire(dir: Vector, target: Vector): Boolean { - return !starship.isInternallyObstructed(getFirePos(), dir) + return !starship.isInternallyObstructed(entity.getFirePos(), dir) } - private fun getFirePos(): Vec3i { - val (x, y, z) = multiblock.getFirePointOffset() - val right = face.rightFace - - return Vec3i( - x = (right.modX * x) + (face.modX * z), - y = y, - z = (right.modZ * x) + (face.modZ * z) - ) - } - - private fun getSign() = starship.world.getBlockAt(pos.x, pos.y, pos.z).getState(false) as? Sign - override fun isIntact(): Boolean { - val sign = getSign() ?: return false - return multiblock.signMatchesStructure(sign, loadChunks = true, particles = false) + return entity.isIntact(checkSign = true) } override fun manualFire(shooter: Damager, dir: Vector, target: Vector) { // Calculate a vector in the direction from the fire point to the targeted block - val vectorToTarget = - target.clone().subtract((getFirePos() + pos).toVector()).normalize().multiply(multiblock.range) + val vectorToTarget = target.clone().subtract((entity.getFirePos()).toVector()).normalize().multiply(multiblock.range) // Add this vector to the fire position to find the position in the direction at max range. - this.targetedBlock = (getFirePos() + pos).toVector().add(vectorToTarget) + this.targetedBlock = (entity.getFirePos()).toVector().add(vectorToTarget) setFiring(!isFiring) // If it is within range, the raycast will move it forward. @@ -124,54 +104,52 @@ class MiningLaserSubsystem( private fun setFiring(firing: Boolean) { val alreadyFiring = starship.subsystems.filterIsInstance().count { it.isFiring } - when (firing) { - true -> { - // Less than but not equal to because it will increase by 1 - if (alreadyFiring < starship.type.maxMiningLasers) { - isFiring = true - starship.informationAction("Enabled mining laser at $pos") - startFiringSequence() - } else { - starship.information("Your ship can only fire ${starship.type.maxMiningLasers} mining lasers at once!") - isFiring = false - } - } - - false -> { + if (firing) { + // Less than but not equal to because it will increase by 1 + if (alreadyFiring < starship.type.maxMiningLasers) { + isFiring = true + starship.informationAction("Enabled mining laser at $pos") + startFiringSequence() + } else { + starship.information("Your ship can only fire ${starship.type.maxMiningLasers} mining lasers at once!") isFiring = false - starship.informationAction("Disabled mining laser at $pos") - starship - cancelTask() } + + return } + + isFiring = false + starship.informationAction("Disabled mining laser at $pos") + starship + cancelTask() } + var tick = 0 + private fun startFiringSequence() { tick = 0 - val fireTask = - runnable { - if (isFiring) { - fire() - } else { - cancel() - } - }.runTaskTimer(IonServer, 0L, 5L) - - starship.world.players.forEach { - if (it.location.distance( - multiblock.getFirePointOffset().plus(pos).toLocation(starship.world) - ) < multiblock.range * 2 - ) { - it.stopSound(multiblock.sound) - - starship.world.playSound( - it.location, - "horizonsend:starship.weapon.mining_laser.start", - SoundCategory.PLAYERS, - 1.0f, - 1.0f - ) + + val fireTask = runnable { + if (isFiring) { + fire() + } else { + cancel() } + }.runTaskTimer(IonServer, 0L, 5L) + + starship.world.players + .filter { it.location.distance(multiblock.getFirePointOffset().plus(pos).toLocation(starship.world)) < multiblock.range * 2 } + .forEach { + + it.stopSound(multiblock.sound) + + starship.world.playSound( + it.location, + "horizonsend:starship.weapon.mining_laser.start", + SoundCategory.PLAYERS, + 1.0f, + 1.0f + ) } firingTasks.add(fireTask) @@ -184,13 +162,7 @@ class MiningLaserSubsystem( // Stop sound for (player in starship.world.players) { - if ( - player.location.distance( - starship.centerOfMass.toLocation(starship.world) - ) > multiblock.range - ) { - continue - } + if (player.location.distance(starship.centerOfMass.toLocation(starship.world)) > multiblock.range) continue starship.world.playSound( player.location, @@ -203,31 +175,23 @@ class MiningLaserSubsystem( } fun fire() { - val initialPos = getFirePos().toLocation(starship.world).toCenterLocation().add(pos.toVector()) + val initialPos = entity.getFirePos().toLocation(starship.world).toCenterLocation() val targetVector = targetedBlock.clone().subtract(initialPos.toVector()) - // Cancel if - val sign = getSign() ?: return cancelTask() val controller = starship.controller - if (!ActiveStarships.isActive(starship)) { - setFiring(false) - return - } + if (!ActiveStarships.isActive(starship)) return setFiring(false) if (!starship.world.ion.hasFlag(WorldFlag.ALLOW_MINING_LASERS)) { - starship.sendMessage( - text("The Mining Laser at ${sign.block.x}, ${sign.block.y}, ${sign.block.z} wasn't able to initialize its gravitational collection beam and was disabled! (Move to a space world)") - ) + starship.userError("The Mining Laser at $pos wasn't able to initialize its gravitational collection beam and was disabled! (Move to a space world)") return setFiring(false) } - val power = PowerMachines.getPower(sign, true) + val power = entity.storage.getPower() if (power == 0) { - starship.alertSubtitle("Mining Laser at ${sign.block.x}, ${sign.block.y}, ${sign.block.z} ran out of power and was disabled!") + starship.alertSubtitle("Mining Laser at $pos ran out of power and was disabled!") - setFiring(false) - return + return setFiring(false) } // Ray trace to get the hit position @@ -246,56 +210,47 @@ class MiningLaserSubsystem( // Create a laser to visualize the beam with a life of 5 ticks val laserEnd = targetedBlock.toLocation(starship.world) - CrystalLaser(initialPos, laserEnd, 5, -1).durationInTicks().apply { start(IonServer) } + val laser = CrystalLaser(initialPos, laserEnd, 5, -1).durationInTicks() + laser.start(IonServer) val blocks = getBlocksToDestroy(laserEnd.block) if (blocks.any { starship.contains(it.x, it.y, it.z) }) { - starship.sendMessage( - text( - "Mining Laser at ${sign.block.x}, ${sign.block.y}, ${sign.block.z} became obstructed and was disabled!" - ).color(NamedTextColor.RED) - ) + starship.alert("Mining Laser at $pos became obstructed and was disabled!") + laser.stop() return setFiring(false) } if (AreaShields.getNearbyAreaShields(laserEnd, multiblock.mineRadius.toDouble()).isNotEmpty()) { - starship.sendMessage( - text( - "Mining Laser at ${sign.block.x}, ${sign.block.y}, ${sign.block.z} targeted an area shield and was disabled!" - ).color(NamedTextColor.RED) - ) + starship.alert("Mining Laser at $pos targeted an area shield and was disabled!") + laser.stop() return setFiring(false) } val blocksBroken = DrillMultiblock.breakBlocks( maxBroken = multiblock.maxBroken, toDestroy = blocks, - output = multiblock.getOutput(sign), - { - val event = StarshipBreakBlockEvent( - controller, - it - ).callEvent() - - controller.canDestroyBlock(it) && event - }, - { - starship.userErrorSubtitle("Not enough space!") - } + output = entity.getOutput() ?: run { setFiring(false); return starship.alert("Mining Laser at $pos's output inventory could not be found!") }, + { controller.canDestroyBlock(it) && StarshipBreakBlockEvent(controller, it).callEvent() }, + { starship.userErrorSubtitle("Not enough space!"); laser.stop() } ) if (blocksBroken > 0) { - PowerMachines.setPower(sign, power - (blockBreakPowerUsage * blocksBroken).toInt(), true) - + entity.storage.removePower((blockBreakPowerUsage * blocksBroken).toInt()) laserEnd.world.spawnParticle(Particle.EXPLOSION, laserEnd, 1) - } else { + } else { starship.sendActionBar(text("Mining laser is trying to break air!", NamedTextColor.RED)) } + playBeamSound() + + tick++ + } + + private fun playBeamSound() { // Sound is 5 seconds, ticks every quarter second if (tick % 20 == 0) { - val soundOrigin = getFirePos().plus(pos).toLocation(starship.world) + val soundOrigin = entity.getFirePos().plus(pos).toLocation(starship.world) soundOrigin.world.players.forEach { if (it.location.distance(soundOrigin) < multiblock.range * 2) { @@ -307,8 +262,6 @@ class MiningLaserSubsystem( tick = 0 } - - tick++ } private fun getBlocksToDestroy(center: Block): MutableList { @@ -338,13 +291,17 @@ class MiningLaserSubsystem( } } - return toDestroy.apply { sortBy { it.location.distanceSquared(pos.toLocation(center.world)) } } + toDestroy.sortBy { it.location.distanceSquared(pos.toLocation(center.world)) } + + return toDestroy } companion object { val MINING_LASER_NOT_MINED = enumSetOf(Material.AIR, Material.BEDROCK, Material.REINFORCED_DEEPSLATE, Material.BARRIER) } + override val powerUsage: Int = 0 + override fun getName(): Component { return text("Mining Laser [how]") } From d53372db4fcf72d7a5dc325ec47e84c33954205a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 14:56:33 -0500 Subject: [PATCH 216/500] auto migrate more legacy entities --- .../entity/type/LegacyMultiblockEntity.kt | 18 +++++++++++++++++- .../defense/passive/areashield/AreaShield.kt | 6 +++++- .../multiblock/type/drills/DrillMultiblock.kt | 7 ++++++- .../type/power/charger/ChargerMultiblock.kt | 6 +++++- .../type/power/storage/PowerBankMultiblock.kt | 14 ++------------ .../type/power/storage/PowerCellMultiblock.kt | 7 ++++++- .../mininglasers/MiningLaserMultiblock.kt | 8 +++++++- 7 files changed, 48 insertions(+), 18 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt index 483ab35e74..3ebbe2a315 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt @@ -1,7 +1,23 @@ package net.horizonsend.ion.server.features.multiblock.entity.type +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.front +import net.kyori.adventure.text.Component import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataType interface LegacyMultiblockEntity { - fun loadFromSign(sign: Sign) {} + fun loadFromSign(sign: Sign) + + fun migrateLegacyPower(sign: Sign) { + this as PoweredMultiblockEntity + val oldPower = sign.persistentDataContainer.get(NamespacedKeys.POWER, PersistentDataType.INTEGER) ?: return + + storage.setPower(oldPower) + + sign.persistentDataContainer.remove(NamespacedKeys.POWER) + sign.front().line(2, Component.empty()) + sign.update() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index b11ebae322..d8535db191 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager @@ -97,7 +98,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< z: Int, world: World, signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( @@ -131,5 +132,8 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< savePowerData(store) } + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 75c7e840b6..892e911161 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity.UserManager import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage @@ -130,7 +131,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M z: Int, world: World, signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { override val storage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 5) override val userManager: UserManager = UserManager(data, persistent = true) @@ -267,6 +268,10 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M override fun displaceAdditional(movement: StarshipMovement) { displayHandler.displace(movement) } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 5e3e7a7e42..908229b141 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.custom.items.component.PowerStorage import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager @@ -101,7 +102,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere z: Int, world: World, signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { override val storage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( @@ -179,5 +180,8 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere savePowerData(store) } + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 7e679c37e5..15ea980f03 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -14,9 +14,6 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.front -import net.kyori.adventure.text.Component.empty import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -24,7 +21,6 @@ import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataType abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { abstract val tierMaterial: Material @@ -152,14 +148,8 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM savePowerData(store) } - override fun loadFromSign(sign: Sign) { - val oldPower = sign.persistentDataContainer.get(NamespacedKeys.POWER, PersistentDataType.INTEGER) ?: return - - storage.setPower(oldPower) - - sign.persistentDataContainer.remove(NamespacedKeys.POWER) - sign.front().line(2, empty()) - sign.update() + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 1d69e50168..97da667a87 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager @@ -13,6 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { @@ -67,7 +69,7 @@ object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock Date: Wed, 9 Oct 2024 15:43:26 -0500 Subject: [PATCH 217/500] region utils --- .../multiblock/entity/MultiblockEntity.kt | 95 ++++++++++++++++--- .../multiblock/type/drills/DrillMultiblock.kt | 25 ++--- 2 files changed, 92 insertions(+), 28 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 1fa66b918c..e475c5b5e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isBlockLoaded +import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block @@ -150,6 +151,25 @@ abstract class MultiblockEntity( ) } + fun displace(movement: StarshipMovement) { + val newX = movement.displaceX(x, z) + val newY = movement.displaceY(y) + val newZ = movement.displaceZ(z, x) + + this.x = newX + this.y = newY + this.z = newZ + + val world = movement.newWorld + if (world != null) { + this.world = world + } + + this.structureDirection = movement.displaceFace(structureDirection) + + displaceAdditional(movement) + } + /** * **/ @@ -167,23 +187,74 @@ abstract class MultiblockEntity( return (getBlockRelative(backFourth, leftRight, upDown).getState(false) as? InventoryHolder)?.inventory } - fun displace(movement: StarshipMovement) { - val newX = movement.displaceX(x, z) - val newY = movement.displaceY(y) - val newZ = movement.displaceZ(z, x) + fun getSquareRegion(offsetRight: Int, offsetUp: Int, offsetForward: Int, radius: Int, depth: Int, filter: (Block) -> Boolean = { true }): MutableList { + val center = getBlockRelative(leftRight = offsetRight, upDown = offsetUp, backFourth = offsetForward) + val right = structureDirection.rightFace - this.x = newX - this.y = newY - this.z = newZ + val blocks = mutableListOf() - val world = movement.newWorld - if (world != null) { - this.world = world + for (h in -radius .. radius) { + for (v in -radius .. radius) { + for (d in 0..depth) { + val block = center.getRelative(right, h).getRelative(BlockFace.UP, v) + if (filter(block)) continue + blocks.add(block) + } + } } - this.structureDirection = movement.displaceFace(structureDirection) + return blocks + } - displaceAdditional(movement) + fun getRegionWithPoints( + minOffsetRight: Int, + minOffsetUp: Int, + minOffsetForward: Int, + maxOffsetRight: Int, + maxOffsetUp: Int, + maxOffsetForward: Int, + predicate: (Block) -> Boolean = { true } + ): MutableList { + val right = structureDirection.rightFace + + val width = maxOffsetRight - minOffsetRight + val height = maxOffsetUp - minOffsetUp + val depth = maxOffsetForward - minOffsetForward + + val origin = getBlockRelative(leftRight = minOffsetRight, upDown = minOffsetUp, backFourth = minOffsetForward) + + val blocks = mutableListOf() + + for (w in 0..width) for (h in 0..height) for (d in 0..depth) { + val block = origin + .getRelative(right, w) + .getRelative(BlockFace.UP, h) + .getRelative(structureDirection, d) + + if (predicate(block)) blocks.add(block) + } + + return blocks + } + + fun getRegionWithDimensions( + originRightOffset: Int, + originUpOffset: Int, + originForwardOffset: Int, + width: Int, + height: Int, + depth: Int, + predicate: (Block) -> Boolean = { true } + ): MutableList { + return getRegionWithPoints( + originRightOffset, + originUpOffset, + originForwardOffset, + originRightOffset + width, + originUpOffset + height, + originForwardOffset + depth, + predicate + ) } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 892e911161..d185a6d295 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -27,9 +27,9 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox -import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.RED @@ -37,7 +37,6 @@ import org.bukkit.Material import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace -import org.bukkit.block.BlockFace.UP import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.block.Action @@ -220,21 +219,12 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } private fun getBlocksToDestroy(): MutableList { - val center = getBlockRelative(4, 0, 0) - val right = structureDirection.rightFace - - val toDestroy = mutableListOf() - - for (h in -multiblock.radius..multiblock.radius) { - for (v in -multiblock.radius..multiblock.radius) { - val block = center.getRelative(right, h).getRelative(UP, v) - if (block.type == Material.AIR) continue - if (block.type == Material.BEDROCK) continue - toDestroy.add(block) - } + val toDestroy = getSquareRegion(4, 0, 0, multiblock.radius, 1) { + it.type == Material.AIR || it.type == Material.BEDROCK } - toDestroy.sortBy { it.location.distanceSquared(center.location) } + val origin = getBlockRelative(4, 0, 0) + toDestroy.sortBy { distanceSquared(it.x, it.y, it.z, origin.x, origin.y, origin.z) } return toDestroy } @@ -321,7 +311,10 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } for (item in drops) { - if (!LegacyItemUtils.canFit(output, item)) return broken + if (!LegacyItemUtils.canFit(output, item)) { + cancel() + return broken + } LegacyItemUtils.addToInventory(output, item) } From 41b499e9a35136ee8d41d4984050cb7f1a634b41 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 17:30:23 -0500 Subject: [PATCH 218/500] migrate crop multis --- .../multiblock/MultiblockRegistration.kt | 13 ++ .../multiblock/entity/MultiblockEntity.kt | 6 +- .../features/multiblock/old/Multiblocks.kt | 13 -- .../multiblock/type/farming/CropMultiblock.kt | 63 ----- .../farming/harvester/HarvesterMultiblock.kt | 217 ++++++++++-------- .../type/farming/planter/PlanterMultiblock.kt | 165 ++++++++----- 6 files changed, 249 insertions(+), 228 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 5ffd71b19a..baebe2aa72 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -18,6 +18,12 @@ import net.horizonsend.ion.server.features.multiblock.type.dockingtube.Disconnec import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium @@ -135,6 +141,13 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(DrillMultiblockTier2) registerMultiblock(DrillMultiblockTier3) + registerMultiblock(PlanterMultiblockTier1) + registerMultiblock(PlanterMultiblockTier2) + registerMultiblock(PlanterMultiblockTier3) + registerMultiblock(HarvesterMultiblockTier1) + registerMultiblock(HarvesterMultiblockTier2) + registerMultiblock(HarvesterMultiblockTier3) + registerMultiblock(MiningLaserMultiblockTier1Top) registerMultiblock(MiningLaserMultiblockTier1Bottom) registerMultiblock(MiningLaserMultiblockTier1Side) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index e475c5b5e2..4254093865 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -250,9 +250,9 @@ abstract class MultiblockEntity( originRightOffset, originUpOffset, originForwardOffset, - originRightOffset + width, - originUpOffset + height, - originForwardOffset + depth, + originRightOffset + (width - 1), + originUpOffset + (height - 1), + originForwardOffset + (depth - 1), predicate ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 9a63b501ac..c0c86e3832 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -14,12 +14,6 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPres import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock @@ -115,13 +109,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(AutoCrafterMultiblockTier1) registerMultiblock(AutoCrafterMultiblockTier2) registerMultiblock(AutoCrafterMultiblockTier3) - - registerMultiblock(PlanterMultiblockTier1) - registerMultiblock(PlanterMultiblockTier2) - registerMultiblock(PlanterMultiblockTier3) - registerMultiblock(HarvesterMultiblockTier1) - registerMultiblock(HarvesterMultiblockTier2) - registerMultiblock(HarvesterMultiblockTier3) } private fun registerMultiblock(multiblock: Multiblock) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt deleted file mode 100644 index d2e1d5d86e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/CropMultiblock.kt +++ /dev/null @@ -1,63 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.farming - -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import org.bukkit.block.Block -import org.bukkit.block.BlockFace -import org.bukkit.block.Sign - -abstract class CropMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { - abstract val regionRadius: Int - abstract val regionDepth: Int - abstract val regionHeight: Int - - /** Get the origin of harvest point. Usually right behind the multiblock */ - protected abstract fun getOriginOffset(): Vec3i - - /** Get the iterable of the blocks contained in the crop region */ - protected fun regionIterable(sign: Sign): Iterable { - val blocks = mutableSetOf() - - val signOrigin = Vec3i(sign.location) - val regionOrigin = getRegionOriginPosition(sign) + signOrigin - - val facing = sign.getFacing().oppositeFace - - val originBlock = getBlockIfLoaded(sign.world, regionOrigin.x, regionOrigin.y, regionOrigin.z) ?: return blocks - blocks += originBlock - - for (depth in 0..regionDepth) { - val depthOffset = originBlock.getRelativeIfLoaded(facing, depth) ?: continue - - for (width in -regionRadius..+regionRadius) { - val widthOffset = depthOffset.getRelativeIfLoaded(facing.rightFace, width) ?: continue - - for (height in 0..regionHeight) { - val heightOffset = widthOffset.getRelativeIfLoaded(BlockFace.UP, height) ?: continue - - blocks += heightOffset - } - } - } - - return blocks - } - - private fun getRegionOriginPosition(sign: Sign): Vec3i { - val (x, y, z) = getOriginOffset() - val facing = sign.getFacing() - val right = facing.rightFace - - return Vec3i( - x = (right.modX * x) + (facing.modX * z), - y = y, - z = (right.modZ * x) + (facing.modZ * z) - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 00d99ded10..00c42c196b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -1,109 +1,46 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.harvester -import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop -import net.horizonsend.ion.server.features.multiblock.type.farming.CropMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component -import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.AQUA +import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA +import net.kyori.adventure.text.format.NamedTextColor.GRAY +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.Ageable -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryHolder +import org.bukkit.persistence.PersistentDataAdapterContext -abstract class HarvesterMultiblock(val tierMaterial: Material, tierNumber: Int) : CropMultiblock() { +abstract class HarvesterMultiblock(val tierMaterial: Material, tierNumber: Int) : Multiblock(), NewPoweredMultiblock { override val name: String = "harvester" override val signText: Array = arrayOf( - Component.text().append(Component.text("Auto ", NamedTextColor.GRAY), Component.text("Harvester", NamedTextColor.GREEN)).build(), - Component.text().append(Component.text("Tier ", NamedTextColor.DARK_AQUA), Component.text(tierNumber, NamedTextColor.AQUA)).build(), + ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), + ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, AQUA)), null, null ) - override val regionRadius: Int = 1 - override val regionHeight: Int = 0 - val powerPerCrop: Int = 10 - - override fun getOriginOffset(): Vec3i = Vec3i(0, -1, -5) - - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - if (furnace.inventory.smelting?.type != Material.PRISMARINE_CRYSTALS) return - if (furnace.inventory.fuel?.type != Material.PRISMARINE_CRYSTALS) return - - val inventory = getInventory(sign) ?: return - event.isCancelled = false - event.isBurning = false - event.burnTime = 200 - - var broken = 0 - val initialPower = PowerMachines.getPower(sign) - - if (initialPower == 0) { - event.burnTime = 800 - return - } - - for (block in regionIterable(sign)) { - val data = block.blockData - - if (data !is Ageable) continue - if (data.age != data.maximumAge) continue - val crop = Crop[block.type] ?: continue - - val drops = crop.getDrops(block).toTypedArray() - - for (item in drops) { - if (!LegacyItemUtils.canFit(inventory, item)) { - event.burnTime = 800 - break - } - } - - if ((broken + 1) * powerPerCrop > initialPower) { - event.burnTime = 800 - break - } - - crop.harvest(block) - broken++ - - val didNotFit = inventory.addItem(*drops) - - if (didNotFit.isNotEmpty()) { - event.burnTime = 800 - break - } - } - - PowerMachines.removePower(sign, broken * powerPerCrop) - } - - private fun getInventoryOffset(): Vec3i = Vec3i(0, 0, -3) - private fun getInventory(sign: Sign): Inventory? { - val (x, y, z) = getInventoryOffset() - val facing = sign.getFacing() - val right = facing.rightFace - - val offset = Vec3i( - x = (right.modX * x) + (facing.modX * z), - y = y, - z = (right.modZ * x) + (facing.modZ * z) - ) - - val (posX, posY, posZ) = offset + Vec3i(sign.location) - - val block = getBlockIfLoaded(sign.world, posX, posY, posZ) ?: return null - return (block.state as? InventoryHolder)?.inventory - } + abstract val regionDepth: Int override fun MultiblockShape.buildStructure() { z(0) { @@ -150,9 +87,109 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, tierNumber: Int) } y(0) { x(-1).anyStairs() - x(0).anyPipedInventory() x(+1).anyStairs() } } } + + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): HarvesterEntity { + return HarvesterEntity( + data, + manager, + this, + x, + y, + z, + world, + structureDirection + ) + } + + class HarvesterEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: HarvesterMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + + override fun tick() { + val inventory = getInventory(leftRight = 0, upDown = 0, backFourth = 2) ?: return tickingManager.sleep(1000) + var broken = 0 + val initialPower = storage.getPower() + + if (initialPower == 0) return tickingManager.sleep(500) + val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) + + for (block in region) { + val data = block.blockData + + if (data !is Ageable) continue + if (data.age != data.maximumAge) continue + val crop = Crop[block.type] ?: continue + + val drops = crop.getDrops(block).toTypedArray() + + for (item in drops) { + if (!LegacyItemUtils.canFit(inventory, item)) { + tickingManager.sleep(800) + break + } + } + + if ((broken + 1) * multiblock.powerPerCrop > initialPower) { + tickingManager.sleep(500) + break + } + + crop.harvest(block) + broken++ + + val didNotFit = inventory.addItem(*drops) + + if (didNotFit.isNotEmpty()) { + tickingManager.sleep(800) + break + } + } + + if (broken == 0) return tickingManager.sleep(100) + + storage.removePower(broken * multiblock.powerPerCrop) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 20f007425f..600a8e4c41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -1,79 +1,46 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.planter -import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop -import net.horizonsend.ion.server.features.multiblock.type.farming.CropMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.NamedTextColor.AQUA +import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA +import net.kyori.adventure.text.format.NamedTextColor.GRAY +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : CropMultiblock() { +abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : Multiblock(), NewPoweredMultiblock { override val name: String = "planter" override val signText: Array = arrayOf( - text().append(text("Auto ", NamedTextColor.GRAY), text("Planter", NamedTextColor.GREEN)).build(), - text().append(text("Tier ", NamedTextColor.DARK_AQUA), text(tierNumber, NamedTextColor.AQUA)).build(), + ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), + ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, AQUA)), null, null ) - override val regionRadius: Int = 1 - override val regionHeight: Int = 0 - - override fun getOriginOffset(): Vec3i = Vec3i(0, -1, -5) - + abstract val regionDepth: Int private val powerPerCrop: Int = 10 - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isCancelled = true - - var planted = 0 - val initialPower = PowerMachines.getPower(sign) - - event.isCancelled = true - val smelting = furnace.inventory.smelting - - if (PowerMachines.getPower(sign) == 0 || smelting?.type != Material.PRISMARINE_CRYSTALS) { - return - } - - val seedItem = furnace.inventory.fuel ?: return - val crop = Crop.findBySeed(seedItem.type) ?: return - - event.isCancelled = false - event.isBurning = false - event.burnTime = 20 - - for (block in regionIterable(sign)) { - if (block.type != Material.AIR) continue - if (seedItem.amount <= 0) break - if (!crop.canBePlanted(block)) continue - if (block.lightLevel < 7) continue - - if ((planted + 1) * powerPerCrop > initialPower) { - event.burnTime = 500 - break - } - - planted++ - seedItem.amount-- - - crop.plant(block) - } - - if (planted == 0) { - event.burnTime = 500 - return - } - - PowerMachines.removePower(sign, planted * powerPerCrop) - } - override fun MultiblockShape.buildStructure() { z(0) { y(-1) { @@ -124,4 +91,84 @@ abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : } } } + + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PlanterEntity { + return PlanterEntity(data, manager, this, x, y, z, world, structureDirection) + } + + class PlanterEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: PlanterMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val storage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + + override fun tick() { + var planted = 0 + val initialPower = storage.getPower() + + val inventory: FurnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return tickingManager.sleep(800) + + val seedItem = inventory.fuel ?: return tickingManager.sleep(500) + val crop = Crop.findBySeed(seedItem.type) ?: return tickingManager.sleep(1000) + + val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) + + for (block in region) { + if (block.type != Material.AIR) continue + if (seedItem.amount <= 0) break + if (!crop.canBePlanted(block)) continue + if (block.lightLevel < 7) continue + + if ((planted + 1) * multiblock.powerPerCrop > initialPower) { + tickingManager.sleep(500) + break + } + + planted++ + seedItem.amount-- + + crop.plant(block) + } + + if (planted == 0) return tickingManager.sleep(300) + + storage.removePower(planted * multiblock.powerPerCrop) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } + } } From de6d33602cd06c514a16aa93be7e437d7467ee16 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 18:13:49 -0500 Subject: [PATCH 219/500] Add sign status displays --- .../display/modular/display/StatusDisplay.kt | 26 ++++++++++++ .../entity/type/StatusMultiblock.kt | 23 ++++++++++ .../farming/harvester/HarvesterMultiblock.kt | 40 ++++++++++++------ .../type/farming/planter/PlanterMultiblock.kt | 42 +++++++++++++------ 4 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt new file mode 100644 index 0000000000..df2327b819 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.client.display.modular.display + +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.kyori.adventure.text.Component + +class StatusDisplay( + private val statusSupplier: StatusMultiblock.StatusManager, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + scale: Float, +) : Display(offsetLeft, offsetUp, offsetBack, scale) { + private val updateHandler: Runnable = Runnable { display() } + + override fun register() { + statusSupplier.updateManager.add(updateHandler) + } + + override fun deRegister() { + statusSupplier.updateManager.remove(updateHandler) + } + + override fun getText(): Component { + return statusSupplier.status + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt new file mode 100644 index 0000000000..0acbe937cd --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt @@ -0,0 +1,23 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.empty + +interface StatusMultiblock { + val statusManager: StatusManager + + fun setStatus(status: Component) { + statusManager.setStatus(status) + } + + class StatusManager { + val updateManager = mutableSetOf() + + var status: Component = empty(); private set + + fun setStatus(status: Component) { + this.status = status + updateManager.forEach { it.run() } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 00c42c196b..440f93e4b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -3,14 +3,16 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.harvester import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock @@ -20,9 +22,12 @@ import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.AQUA +import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN +import net.kyori.adventure.text.format.NamedTextColor.RED +import net.kyori.adventure.text.format.TextDecoration.ITALIC import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -30,7 +35,7 @@ import org.bukkit.block.Sign import org.bukkit.block.data.Ageable import org.bukkit.persistence.PersistentDataAdapterContext -abstract class HarvesterMultiblock(val tierMaterial: Material, tierNumber: Int) : Multiblock(), NewPoweredMultiblock { +abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int) : Multiblock(), NewPoweredMultiblock { override val name: String = "harvester" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), @@ -114,16 +119,29 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, tierNumber: Int) z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() override val storage: PowerStorage = loadStoredPower(data) - override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + override val tickingManager: TickingManager = TickingManager(interval = 20) + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + private fun cancelWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } override fun tick() { val inventory = getInventory(leftRight = 0, upDown = 0, backFourth = 2) ?: return tickingManager.sleep(1000) var broken = 0 + val initialPower = storage.getPower() + if (initialPower == 0) return cancelWithStatus(text("No Power", RED), 500) - if (initialPower == 0) return tickingManager.sleep(500) val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) for (block in region) { @@ -153,25 +171,23 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, tierNumber: Int) val didNotFit = inventory.addItem(*drops) if (didNotFit.isNotEmpty()) { - tickingManager.sleep(800) + cancelWithStatus(text("No Space", RED), 500) break } + + if (broken >= multiblock.tierNumber) break } - if (broken == 0) return tickingManager.sleep(100) + if (broken == 0) return cancelWithStatus(text("Sleeping", BLUE, ITALIC), 100) storage.removePower(broken * multiblock.powerPerCrop) + setStatus(text("Working", GREEN)) } override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) } - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() - override fun onLoad() { displayHandler.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 600a8e4c41..a1901f17d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -3,14 +3,16 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.planter import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock @@ -19,9 +21,12 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.AQUA +import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN +import net.kyori.adventure.text.format.NamedTextColor.RED +import net.kyori.adventure.text.format.TextDecoration.ITALIC import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -29,7 +34,7 @@ import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : Multiblock(), NewPoweredMultiblock { +abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int) : Multiblock(), NewPoweredMultiblock { override val name: String = "planter" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), @@ -105,18 +110,31 @@ abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { override val storage: PowerStorage = loadStoredPower(data) - override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + override val tickingManager: TickingManager = TickingManager(interval = 20) + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + private fun cancelWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } override fun tick() { var planted = 0 val initialPower = storage.getPower() + if (initialPower == 0) return cancelWithStatus(text("No Power", RED), 500) val inventory: FurnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return tickingManager.sleep(800) - val seedItem = inventory.fuel ?: return tickingManager.sleep(500) - val crop = Crop.findBySeed(seedItem.type) ?: return tickingManager.sleep(1000) + val seedItem = inventory.fuel ?: return cancelWithStatus(text("No Seeds", RED), 500) + val crop = Crop.findBySeed(seedItem.type) ?: return cancelWithStatus( text("Unknown Crop", RED), 1000) val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) @@ -124,7 +142,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : if (block.type != Material.AIR) continue if (seedItem.amount <= 0) break if (!crop.canBePlanted(block)) continue - if (block.lightLevel < 7) continue + if (block.lightFromBlocks < 7 && block.lightFromSky < 7) continue if ((planted + 1) * multiblock.powerPerCrop > initialPower) { tickingManager.sleep(500) @@ -135,22 +153,20 @@ abstract class PlanterMultiblock(val tierMaterial: Material, tierNumber: Int) : seedItem.amount-- crop.plant(block) + + if (planted >= multiblock.tierNumber) break } - if (planted == 0) return tickingManager.sleep(300) + if (planted == 0) return cancelWithStatus(text("Sleeping", BLUE, ITALIC), 100) storage.removePower(planted * multiblock.powerPerCrop) + setStatus(text("Working", GREEN)) } override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) } - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() - override fun onLoad() { displayHandler.update() } From 7b403fd617894319e3c19740f2ef7c320dec269e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 18:40:05 -0500 Subject: [PATCH 220/500] migrate incinerators, rename storage to powerStorage for clarity, standardize relative coordinate order --- .../ion/server/command/qol/SetPowerCommand.kt | 2 +- .../modular/display/PowerEntityDisplay.kt | 2 +- .../server/features/machine/AreaShields.kt | 8 +- .../multiblock/MultiblockRegistration.kt | 9 ++ .../multiblock/entity/MultiblockEntity.kt | 16 +-- .../entity/type/LegacyMultiblockEntity.kt | 2 +- .../type/power/PoweredMultiblockEntity.kt | 4 +- .../features/multiblock/old/Multiblocks.kt | 7 - .../multiblock/shape/MultiblockShape.kt | 2 +- .../multiblock/type/NewPoweredMultiblock.kt | 6 +- .../defense/passive/areashield/AreaShield.kt | 2 +- .../multiblock/type/drills/DrillMultiblock.kt | 10 +- .../farming/harvester/HarvesterMultiblock.kt | 8 +- .../type/farming/planter/PlanterMultiblock.kt | 6 +- .../type/fluid/ElectrolysisMultiblock.kt | 2 +- .../type/misc/DisposalMultiblock.kt | 127 ++++++++++-------- .../type/power/charger/ChargerMultiblock.kt | 6 +- .../type/power/storage/PowerBankMultiblock.kt | 4 +- .../type/power/storage/PowerCellMultiblock.kt | 2 +- .../mininglasers/MiningLaserMultiblock.kt | 14 +- .../subsystem/misc/MiningLaserSubsystem.kt | 4 +- .../node/manager/PowerNodeManager.kt | 10 +- .../node/type/power/PowerInputNode.kt | 12 +- .../utils/coordinates/RelativeCoordinates.kt | 12 +- 24 files changed, 149 insertions(+), 128 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt index afa10b2ee1..b5d42da9c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt @@ -42,7 +42,7 @@ object SetPowerCommand : SLCommand() { val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) if (entity !is PoweredMultiblockEntity) continue - entity.storage.setPower(amount) + entity.powerStorage.setPower(amount) hits++ sender.debug("power sent") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt index 1dbe1c2145..edcf0b3915 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt @@ -33,5 +33,5 @@ class PowerEntityDisplay( return title?.let { ofChildren(it, newline(), formatPower()) } ?: formatPower() } - private fun formatPower(): Component = ofChildren(prefixComponent, text(multiblockEntity.storage.getPower(), NamedTextColor.GREEN)) + private fun formatPower(): Component = ofChildren(prefixComponent, text(multiblockEntity.powerStorage.getPower(), NamedTextColor.GREEN)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index 172a4ea50e..81c0b78bfb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -93,13 +93,13 @@ object AreaShields : IonServerComponent() { blockList.forEach { explosionResistanceTotal += it.type.blastResistance } for (shield in areaShields) { - var power = shield.storage.getPower() + var power = shield.powerStorage.getPower() if (power <= 0) continue power -= ((blockList.size.toDouble()/explosionResistanceTotal) * 10 * (this.explosionPowerOverride ?: 1.0)).toInt() - val percent = power.toFloat() / shield.storage.capacity.toFloat() + val percent = power.toFloat() / shield.powerStorage.capacity.toFloat() - if (usePower) shield.storage.setPower(power) + if (usePower) shield.powerStorage.setPower(power) val color = Color.fromRGB( min(255f, 255 - max(0f, 255 * percent)).toInt(), @@ -125,7 +125,7 @@ object AreaShields : IonServerComponent() { val areaShields = getNearbyAreaShields(event.entity.location, 1.0) for (shield in areaShields) { - if (shield.storage.getPower() > 0) event.isCancelled = true + if (shield.powerStorage.getPower() > 0) event.isCancelled = true } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index baebe2aa72..1a119e21c5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -30,6 +30,7 @@ import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTa import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock @@ -57,6 +58,8 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.OdometerMult import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BattleCruiserReactorMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.CruiserReactorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.AmplifiedGravityWellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.StandardGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass1 import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass2 import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass3 @@ -148,6 +151,9 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(HarvesterMultiblockTier2) registerMultiblock(HarvesterMultiblockTier3) + registerMultiblock(DisposalMultiblock) + + // Moreso powered multis than ship multis, could go in either spot tbh registerMultiblock(MiningLaserMultiblockTier1Top) registerMultiblock(MiningLaserMultiblockTier1Bottom) registerMultiblock(MiningLaserMultiblockTier1Side) @@ -246,6 +252,9 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(BoxShieldMultiblock) registerMultiblock(EventShieldMultiblock) + registerMultiblock(StandardGravityWellMultiblock) + registerMultiblock(AmplifiedGravityWellMultiblock) + // Machine registerMultiblock(ShipFactoryMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 4254093865..f93e96ddbf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -173,22 +173,22 @@ abstract class MultiblockEntity( /** * **/ - fun getBlockRelative(backFourth: Int, leftRight: Int, upDown: Int): Block { - val (x, y, z) = getRelative(vec3i, structureDirection, backFourth, leftRight, upDown) + fun getBlockRelative(right: Int, up: Int, forward: Int): Block { + val (x, y, z) = getRelative(vec3i, structureDirection, right = right, up = up, forward = forward) return world.getBlockAt(x, y, z) } - fun getPosRelative(backFourth: Int, leftRight: Int, upDown: Int): Vec3i { - return getRelative(vec3i, structureDirection, backFourth, leftRight, upDown) + fun getPosRelative(forward: Int, right: Int, up: Int): Vec3i { + return getRelative(vec3i, structureDirection, right = right, up = up, forward = forward) } - fun getInventory(backFourth: Int, leftRight: Int, upDown: Int): Inventory? { - return (getBlockRelative(backFourth, leftRight, upDown).getState(false) as? InventoryHolder)?.inventory + fun getInventory(right: Int, up: Int, forward: Int): Inventory? { + return (getBlockRelative( right = right, up = up, forward = forward).getState(false) as? InventoryHolder)?.inventory } fun getSquareRegion(offsetRight: Int, offsetUp: Int, offsetForward: Int, radius: Int, depth: Int, filter: (Block) -> Boolean = { true }): MutableList { - val center = getBlockRelative(leftRight = offsetRight, upDown = offsetUp, backFourth = offsetForward) + val center = getBlockRelative(right = offsetRight, up = offsetUp, forward = offsetForward) val right = structureDirection.rightFace val blocks = mutableListOf() @@ -221,7 +221,7 @@ abstract class MultiblockEntity( val height = maxOffsetUp - minOffsetUp val depth = maxOffsetForward - minOffsetForward - val origin = getBlockRelative(leftRight = minOffsetRight, upDown = minOffsetUp, backFourth = minOffsetForward) + val origin = getBlockRelative(right = minOffsetRight, up = minOffsetUp, forward = minOffsetForward) val blocks = mutableListOf() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt index 3ebbe2a315..5fd38bfaf4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt @@ -14,7 +14,7 @@ interface LegacyMultiblockEntity { this as PoweredMultiblockEntity val oldPower = sign.persistentDataContainer.get(NamespacedKeys.POWER, PersistentDataType.INTEGER) ?: return - storage.setPower(oldPower) + powerStorage.setPower(oldPower) sign.persistentDataContainer.remove(NamespacedKeys.POWER) sign.front().line(2, Component.empty()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index d197a410d6..56756e106e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -7,13 +7,13 @@ import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { val multiblock: NewPoweredMultiblock<*> - val storage: PowerStorage + val powerStorage: PowerStorage fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) } fun savePowerData(store: PersistentMultiblockData) { - store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, storage.getPower()) + store.addAdditionalData(NamespacedKeys.POWER, PersistentDataType.INTEGER, powerStorage.getPower()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index c0c86e3832..aa3dbbc8d9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -24,7 +24,6 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMu import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 @@ -37,8 +36,6 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinter import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.AmplifiedGravityWellMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell.StandardGravityWellMultiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement @@ -91,15 +88,11 @@ object Multiblocks : IonServerComponent() { registerMultiblock(GlassPrinterMultiblock) registerMultiblock(ArmorPrinterMultiblock) - registerMultiblock(StandardGravityWellMultiblock) - registerMultiblock(AmplifiedGravityWellMultiblock) - registerMultiblock(StandardAmmoPressMultiblock) registerMultiblock(AmmoLoaderMultiblock) registerMultiblock(MissileLoaderMultiblock) registerMultiblock(DecomposerMultiblock) - registerMultiblock(DisposalMultiblock) registerMultiblock(ItemSplitterMultiblock) registerMultiblock(GasCollectorMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 6836574e6f..5b1168559d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -252,7 +252,7 @@ class MultiblockShape { } CARDINAL_BLOCK_FACES.forEach { inwardFace -> - val vec = toAbsolute(inwardFace, inward, right, upward) + val vec = toAbsolute(inwardFace, right, upward, inward) val requirementMap = getRequirementMap(inwardFace) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt index cd1c3f0926..a2c2f027a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt @@ -21,15 +21,15 @@ interface NewPoweredMultiblock : EntityMultiblock { var powerToTransfer = power * item.amount if (powerToTransfer == 0) return - val machinePower = entity.storage.getPower() - val maxMachinePower = entity.storage.capacity + val machinePower = entity.powerStorage.getPower() + val maxMachinePower = entity.powerStorage.capacity if (maxMachinePower - machinePower < powerToTransfer) { powerToTransfer = maxMachinePower - machinePower } setPower(item, power - powerToTransfer / item.amount) - entity.storage.addPower(powerToTransfer) + entity.powerStorage.addPower(powerToTransfer) } companion object : SLEventListener() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index d8535db191..6103b2ed2c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -99,7 +99,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< world: World, signDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val storage: PowerStorage = loadStoredPower(data) + override val powerStorage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index d185a6d295..00b73db744 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -131,7 +131,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M world: World, signDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { - override val storage: PowerStorage = loadStoredPower(data) + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 5) override val userManager: UserManager = UserManager(data, persistent = true) @@ -149,7 +149,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M if (drills > 16) return player.userErrorAction("You cannot use more than 16 drills at once!") if (!isEnabled()) return - val power = storage.getPower() + val power = powerStorage.getPower() if (power == 0) { disable() return player.alertSubtitle("Your drill at $vec3i ran out of power! It was disabled.") @@ -168,7 +168,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M val broken = breakBlocks( maxBroken, toDestroy, - getInventory(0, -1, 0) ?: return run { + getInventory(-1, 0, 0) ?: return run { player.userError("Drill output inventory destroyed") disable() }, @@ -185,7 +185,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M ) val powerUsage = broken * 50 - storage.setPower(power - powerUsage) + powerStorage.setPower(power - powerUsage) } fun handleClick(sign: Sign, player: Player) { @@ -223,7 +223,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M it.type == Material.AIR || it.type == Material.BEDROCK } - val origin = getBlockRelative(4, 0, 0) + val origin = getBlockRelative(0, 0, 4) toDestroy.sortBy { distanceSquared(it.x, it.y, it.z, origin.x, origin.y, origin.z) } return toDestroy diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 440f93e4b1..2dfd157220 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -121,7 +121,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I structureDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() - override val storage: PowerStorage = loadStoredPower(data) + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 20) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( @@ -136,10 +136,10 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I } override fun tick() { - val inventory = getInventory(leftRight = 0, upDown = 0, backFourth = 2) ?: return tickingManager.sleep(1000) + val inventory = getInventory(right = 0, up = 0, forward = 2) ?: return tickingManager.sleep(1000) var broken = 0 - val initialPower = storage.getPower() + val initialPower = powerStorage.getPower() if (initialPower == 0) return cancelWithStatus(text("No Power", RED), 500) val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) @@ -180,7 +180,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I if (broken == 0) return cancelWithStatus(text("Sleeping", BLUE, ITALIC), 100) - storage.removePower(broken * multiblock.powerPerCrop) + powerStorage.removePower(broken * multiblock.powerPerCrop) setStatus(text("Working", GREEN)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index a1901f17d5..8073599e7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -111,7 +111,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int world: World, structureDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { - override val storage: PowerStorage = loadStoredPower(data) + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 20) override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() @@ -128,7 +128,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int override fun tick() { var planted = 0 - val initialPower = storage.getPower() + val initialPower = powerStorage.getPower() if (initialPower == 0) return cancelWithStatus(text("No Power", RED), 500) val inventory: FurnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return tickingManager.sleep(800) @@ -159,7 +159,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int if (planted == 0) return cancelWithStatus(text("Sleeping", BLUE, ITALIC), 100) - storage.removePower(planted * multiblock.powerPerCrop) + powerStorage.removePower(planted * multiblock.powerPerCrop) setStatus(text("Working", GREEN)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 4f4d17794a..9008abc1e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -223,7 +223,7 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock = arrayOf( loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER)), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt index 59c0a02045..c82daae7d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt @@ -1,25 +1,29 @@ package net.horizonsend.ion.server.features.multiblock.type.misc -import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.leftFace -import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Material +import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Furnace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryHolder +import org.bukkit.persistence.PersistentDataAdapterContext import kotlin.math.roundToInt -abstract class AbstractDisposalMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object AbstractDisposalMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "incinerator" override var signText: Array = arrayOf( @@ -29,11 +33,9 @@ abstract class AbstractDisposalMultiblock : Multiblock(), PowerStoringMultiblock null ) - companion object { - private const val powerConsumed = 0.5 - } - override val maxPower: Int = 150_000 + + private const val powerConsumed = 0.5 abstract val mirrored: Boolean override fun MultiblockShape.buildStructure() { @@ -86,54 +88,71 @@ abstract class AbstractDisposalMultiblock : Multiblock(), PowerStoringMultiblock } } - private fun getOutput(sign: Sign): Inventory { - val direction = sign.getFacing().oppositeFace - return if (!mirrored) ( - sign.block.getRelative(direction) - .getRelative(direction.leftFace) - .getRelative(BlockFace.DOWN) - .getState(false) as InventoryHolder - ).inventory else ( - sign.block.getRelative(direction) - .getRelative(direction.rightFace) - .getRelative(BlockFace.DOWN) - .getState(false) as InventoryHolder - ).inventory + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): DisposalMultiblockEntity { + return DisposalMultiblockEntity(data, manager, x, y, z, world, structureDirection) } - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - event.isBurning = false - event.burnTime = 0 - val inventory = getOutput(sign) - val power = PowerMachines.getPower(sign) - if (power == 0) return + class DisposalMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, DisposalMultiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val multiblock: DisposalMultiblock = DisposalMultiblock + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + + override fun tick() { + val inventory = getInventory(if (multiblock.mirrored) 1 else -1, -1, 0) ?: return + val power = powerStorage.getPower() + if (power == 0) return tickingManager.sleep(20) + + var amountToClear = 0 + + if (inventory.isEmpty) return tickingManager.sleep(50) + + // Clear while checking for power + for (i in 0 until inventory.size) { + val size = (inventory.getItem(i) ?: continue).amount + if ((size * powerConsumed) + (amountToClear * 3) >= power) continue + amountToClear += size + inventory.clear(i) + } + + powerStorage.removePower((powerConsumed * amountToClear).roundToInt()) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } - var amountToClear = 0 + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() - if (inventory.isEmpty) { - event.burnTime = 200 + override fun onLoad() { + displayHandler.update() + } - return + override fun onUnload() { + displayHandler.remove() } - // Clear while checking for power - for (i in 0 until inventory.size) { - val size = (inventory.getItem(i) ?: continue).amount - if ((size * powerConsumed) + (amountToClear * 3) >= power) continue - amountToClear += size - inventory.clear(i) + override fun handleRemoval() { + displayHandler.remove() } - PowerMachines.setPower(sign, power - (powerConsumed * amountToClear).roundToInt()) - furnace.cookTime = 20.toShort() + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } - event.isCancelled = true - event.isBurning = false - event.burnTime = 20 + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } @@ -143,4 +162,4 @@ object DisposalMultiblock : AbstractDisposalMultiblock() { object DisposalMultiblockMirrored : AbstractDisposalMultiblock() { override val mirrored = true -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 908229b141..46afe3adb2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -103,7 +103,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere world: World, signDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val storage: PowerStorage = loadStoredPower(data) + override val powerStorage: PowerStorage = loadStoredPower(data) private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, @@ -111,7 +111,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere ).register() fun handleCharging(event: FurnaceBurnEvent, furnace: Furnace) { - val availablePower = storage.getPower() + val availablePower = powerStorage.getPower() if (availablePower == 0) return val item = event.fuel @@ -151,7 +151,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere powerManager.addPower(item, customItem, multiplier) - storage.setPower(power - multiplier * item.amount) + powerStorage.setPower(power - multiplier * item.amount) furnace.cookTime = 20.toShort() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 15ea980f03..fa0345e9be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -87,7 +87,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { val b = getMultiblockEntity(sign) ?: return - player.information("b: ${b.storage.getPower()}") + player.information("b: ${b.powerStorage.getPower()}") } override fun createEntity( @@ -121,7 +121,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM world: World, structureDirection: BlockFace ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val storage: PowerStorage = loadStoredPower(data) + override val powerStorage: PowerStorage = loadStoredPower(data) private val displayHandler = newMultiblockSignOverlay( this, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 97da667a87..83cbb533d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -70,7 +70,7 @@ object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock 0) { - entity.storage.removePower((blockBreakPowerUsage * blocksBroken).toInt()) + entity.powerStorage.removePower((blockBreakPowerUsage * blocksBroken).toInt()) laserEnd.world.spawnParticle(Particle.EXPLOSION, laserEnd, 1) } else { starship.sendActionBar(text("Mining laser is trying to break air!", NamedTextColor.RED)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index 52c5fc746e..da64838807 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -45,15 +45,15 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager = getPowerInputs(extractorNode) destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) if (destinations.isEmpty()) return@submit - val transferred = minOf(source.storage.getPower(), powerCheck) - val notRemoved = source.storage.removePower(transferred) + val transferred = minOf(source.powerStorage.getPower(), powerCheck) + val notRemoved = source.powerStorage.removePower(transferred) val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) if (transferred == remainder) { @@ -61,7 +61,7 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager 0) { - source.storage.addPower(remainder) + source.powerStorage.addPower(remainder) } } @@ -145,7 +145,7 @@ private fun runPowerTransfer(source: TransportNode, destinations: List?, transferred: Int) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt index 62ca399258..0de1cb7321 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt @@ -32,7 +32,7 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(), Pow fun isCalling(): Boolean { val entities = getPoweredEntities() if (entities.isEmpty()) return false - return entities.any { it.storage.getRemainingCapacity() > 0 } + return entities.any { it.powerStorage.getRemainingCapacity() > 0 } } fun getPoweredEntities(): Collection { @@ -51,12 +51,12 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(), Pow } fun distributePower(power: Int): Int { - val entities = getPoweredEntities().filterTo(mutableListOf()) { !it.storage.isFull() } + val entities = getPoweredEntities().filterTo(mutableListOf()) { !it.powerStorage.isFull() } if (entities.isEmpty()) return power // Skip math for most scenarios - if (entities.size == 1) return entities.first().storage.addPower(power) + if (entities.size == 1) return entities.first().powerStorage.addPower(power) var remainingPower = power @@ -64,15 +64,15 @@ class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(), Pow if (entities.isEmpty()) break val share = remainingPower / entities.size - val minRemaining = entities.minOf { it.storage.getRemainingCapacity() } + val minRemaining = entities.minOf { it.powerStorage.getRemainingCapacity() } val distributed = minOf(minRemaining, share) val iterator = entities.iterator() while (iterator.hasNext()) { val entity = iterator.next() - val r = entity.storage.addPower(distributed) - if (entity.storage.isFull()) iterator.remove() + val r = entity.powerStorage.addPower(distributed) + if (entity.powerStorage.isFull()) iterator.remove() remainingPower -= (distributed - r) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt index 43b3d41bb4..31ca650bb8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeCoordinates.kt @@ -3,18 +3,18 @@ package net.horizonsend.ion.server.miscellaneous.utils.coordinates import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.block.BlockFace -fun toAbsolute(forwardFace: BlockFace, backFourth: Int, leftRight: Int, upDown: Int): Vec3i { +fun toAbsolute(forwardFace: BlockFace, right: Int, up: Int, forward: Int): Vec3i { val rightFace = forwardFace.rightFace return Vec3i( - x = rightFace.modX * leftRight + forwardFace.modX * backFourth, - y = upDown, - z = rightFace.modZ * leftRight + forwardFace.modZ * backFourth + x = rightFace.modX * right + forwardFace.modX * forward, + y = up, + z = rightFace.modZ * right + forwardFace.modZ * forward ) } -fun getRelative(origin: Vec3i, forwardFace: BlockFace, forward: Int, right: Int, up: Int): Vec3i { - val relative = toAbsolute(forwardFace, forward, right, up) +fun getRelative(origin: Vec3i, forwardFace: BlockFace, right: Int, up: Int, forward: Int): Vec3i { + val relative = toAbsolute(forwardFace, right, up, forward) return origin + relative } From 894c175dda8d9a3012a8b4f7fb6b8b189eaf1bf9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 21:32:52 -0500 Subject: [PATCH 221/500] migrate printers --- .../multiblock/MultiblockRegistration.kt | 10 ++ .../features/multiblock/old/Multiblocks.kt | 18 +-- .../type/printer/PrinterMultiblock.kt | 132 +++++++++++++----- 3 files changed, 111 insertions(+), 49 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 1a119e21c5..6ac071f24c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -53,6 +53,10 @@ import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBa import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerCellMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock @@ -153,6 +157,12 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(DisposalMultiblock) + // Furnace powered multis + registerMultiblock(CarbonPrinterMultiblock) + registerMultiblock(TechnicalPrinterMultiblock) + registerMultiblock(GlassPrinterMultiblock) + registerMultiblock(ArmorPrinterMultiblock) + // Moreso powered multis than ship multis, could go in either spot tbh registerMultiblock(MiningLaserMultiblockTier1Top) registerMultiblock(MiningLaserMultiblockTier1Bottom) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index aa3dbbc8d9..310e1ea644 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -31,11 +31,7 @@ import net.horizonsend.ion.server.features.multiblock.type.power.generator.Gener import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement @@ -66,6 +62,7 @@ object Multiblocks : IonServerComponent() { } private fun initMultiblocks() { + // Furnace start registerMultiblock(CentrifugeMultiblock) registerMultiblock(CompressorMultiblock) registerMultiblock(FabricatorMultiblock) @@ -83,21 +80,18 @@ object Multiblocks : IonServerComponent() { registerMultiblock(CarbonProcessorMultiblock) - registerMultiblock(CarbonPrinterMultiblock) - registerMultiblock(TechnicalPrinterMultiblock) - registerMultiblock(GlassPrinterMultiblock) - registerMultiblock(ArmorPrinterMultiblock) - registerMultiblock(StandardAmmoPressMultiblock) registerMultiblock(AmmoLoaderMultiblock) registerMultiblock(MissileLoaderMultiblock) + registerMultiblock(GasCollectorMultiblock) + registerMultiblock(VentMultiblock) + registerMultiblock(GasPowerPlantMultiblock) + // Furnace end + registerMultiblock(DecomposerMultiblock) registerMultiblock(ItemSplitterMultiblock) - registerMultiblock(GasCollectorMultiblock) - registerMultiblock(GasPowerPlantMultiblock) - registerMultiblock(VentMultiblock) registerMultiblock(AutoCrafterMultiblockTier1) registerMultiblock(AutoCrafterMultiblockTier2) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt index 4b0bdbc07d..8ba4a4ad4c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt @@ -1,20 +1,34 @@ package net.horizonsend.ion.server.features.multiblock.type.printer -import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.RED import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.InventoryHolder +import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PrinterMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +abstract class PrinterMultiblock : Multiblock(), NewPoweredMultiblock { override val name: String = "printer" override val maxPower: Int = 50_000 abstract fun getOutput(product: Material): ItemStack @@ -115,41 +129,85 @@ abstract class PrinterMultiblock : Multiblock(), PowerStoringMultiblock, Furnace } } - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - event.isCancelled = true - val smelting = furnace.inventory.smelting - val fuel = furnace.inventory.fuel - - if (PowerMachines.getPower(sign) < 250 - || smelting == null - || smelting.type != Material.PRISMARINE_CRYSTALS - || fuel == null - || fuel.type != Material.COBBLESTONE - ) { - return + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PrinterEntity { + return PrinterEntity(data, manager, this, x, y, z, world, structureDirection) + } + + class PrinterEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: PrinterMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickingManager = TickingManager(interval = 20) + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + private fun cancelWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) } - event.isBurning = false - event.burnTime = 100 - furnace.cookTime = (-1000).toShort() - event.isCancelled = false + override fun tick() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return cancelWithStatus(text("No Furnace"), 250) + val outputInventory = getInventory(0, 0, 4) ?: return cancelWithStatus(text("No Output Inventory", RED), 250) + + val fuel = furnaceInventory.fuel + + if (powerStorage.getPower() < 250) return cancelWithStatus(text("No Power", RED), 100) + if (fuel?.type != Material.COBBLESTONE) return cancelWithStatus(text("Out of Cobblestone", RED), 100) + + val product = getBlockRelative(0, 0, 2).type + val output = multiblock.getOutput(product) - val direction = sign.getFacing().oppositeFace + if (!LegacyItemUtils.canFit(outputInventory, output)) return cancelWithStatus(text("No Space", RED), 100) + LegacyItemUtils.addToInventory(outputInventory, output) - val state = sign.block.getRelative(direction, 5).getState(false) as? InventoryHolder ?: return + fuel.amount-- - val product = sign.block.getRelative(sign.getFacing().oppositeFace, 3).type - val output = getOutput(product) + powerStorage.removePower(250) + tickingManager.sleep(100) - val inventory = state.inventory - if (!LegacyItemUtils.canFit(inventory, output)) return + val furnace = furnaceInventory.holder ?: return + + furnace.burnTime = Short.MAX_VALUE + furnace.cookTime = 100 + + furnace.update() + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } - LegacyItemUtils.addToInventory(inventory, output) - fuel.amount = fuel.amount - 1 - PowerMachines.removePower(sign, 250) + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } From 159c91d3b2eefe18eeb2eca289e3049830083093 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 9 Oct 2024 22:08:37 -0500 Subject: [PATCH 222/500] migrate carbon processor --- .../multiblock/MultiblockRegistration.kt | 3 + .../features/multiblock/old/Multiblocks.kt | 3 - .../type/printer/CarbonProcessorMultiblock.kt | 149 ++++++++++++------ .../type/printer/PrinterMultiblock.kt | 5 +- 4 files changed, 109 insertions(+), 51 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 6ac071f24c..5e0574873d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -55,6 +55,7 @@ import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBa import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerCellMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.LandingGearMultiblock @@ -163,6 +164,8 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(GlassPrinterMultiblock) registerMultiblock(ArmorPrinterMultiblock) + registerMultiblock(CarbonProcessorMultiblock) + // Moreso powered multis than ship multis, could go in either spot tbh registerMultiblock(MiningLaserMultiblockTier1Top) registerMultiblock(MiningLaserMultiblockTier1Bottom) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 310e1ea644..6bcad49258 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -31,7 +31,6 @@ import net.horizonsend.ion.server.features.multiblock.type.power.generator.Gener import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement @@ -78,8 +77,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(PowerFurnaceMultiblockTier2) registerMultiblock(PowerFurnaceMultiblockTier3) - registerMultiblock(CarbonProcessorMultiblock) - registerMultiblock(StandardAmmoPressMultiblock) registerMultiblock(AmmoLoaderMultiblock) registerMultiblock(MissileLoaderMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt index d25503b7bc..70ea46f5d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt @@ -1,24 +1,37 @@ package net.horizonsend.ion.server.features.multiblock.type.printer -import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isConcretePowder import net.horizonsend.ion.server.miscellaneous.utils.isStainedGlass +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.Material -import org.bukkit.block.Block +import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Furnace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.InventoryHolder +import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext -object CarbonProcessorMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object CarbonProcessorMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower: Int = 30000 override val name = "processor" @@ -73,55 +86,99 @@ object CarbonProcessorMultiblock : Multiblock(), PowerStoringMultiblock, Furnace } } - fun getOutputBlock(sign: Block): Block { - return sign.getRelative((sign.getState(false) as Sign).getFacing().oppositeFace, 3) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): CarbonProcessorEntity { + return CarbonProcessorEntity(data, manager, x, y, z, world, structureDirection) } - fun getOutput(sign: Block, inputType: ItemStack): ItemStack { - val direction: BlockFace = (sign.getState(false) as Sign).getFacing().oppositeFace + class CarbonProcessorEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, CarbonProcessorMultiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { + override val multiblock = CarbonProcessorMultiblock + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 1) + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + private fun cancelWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } + + override fun tick() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return cancelWithStatus(text("No Furnace"), 250) + val outputInventory = getInventory(0, 0, 2) ?: return cancelWithStatus(text("No Output Inventory", NamedTextColor.RED), 250) + + val fuel = furnaceInventory.fuel + + if (powerStorage.getPower() < 250) return cancelWithStatus(text("No Power", NamedTextColor.RED), 100) + if (fuel?.type?.isConcretePowder != true) return cancelWithStatus(text("Out of Powder", NamedTextColor.RED), 100) + + val output = getOutput(fuel) + + if (!LegacyItemUtils.canFit(outputInventory, output)) return cancelWithStatus(text("No Space", NamedTextColor.RED), 100) + LegacyItemUtils.addToInventory(outputInventory, output) - val glassType = sign.getRelative(direction, 2).type + fuel.amount-- - if (glassType.isStainedGlass) { - val concreteTypeName = glassType.name.replace("STAINED_GLASS", "CONCRETE") - val outputType = Material.getMaterial(concreteTypeName) ?: error("No material $concreteTypeName") + powerStorage.removePower(250) - return ItemStack(outputType, 1) + cancelWithStatus(text("Working", GREEN), 50) + + val furnace = furnaceInventory.holder ?: return + + furnace.burnTime = Short.MAX_VALUE + furnace.cookTime = 50 + + furnace.update() } - val existingType = inputType.type - return ItemStack(Material.getMaterial(existingType.name.removeSuffix("_POWDER")) ?: error("No material $glassType"), 1) - } + fun getOutput(inputType: ItemStack): ItemStack { + val glassType = getBlockRelative(0, 0, 1).type + + if (glassType.isStainedGlass) { + val concreteTypeName = glassType.name.replace("STAINED_GLASS", "CONCRETE") + val outputType = Material.getMaterial(concreteTypeName) ?: error("No material $concreteTypeName") - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - event.isCancelled = true - val smelting = furnace.inventory.smelting - val fuel = furnace.inventory.fuel - if (PowerMachines.getPower(sign) == 0 || - smelting == null || - smelting.type != Material.PRISMARINE_CRYSTALS || - fuel == null || - !fuel.type.isConcretePowder - ) { - return + return ItemStack(outputType, 1) + } + + val existingType = inputType.type + return ItemStack(Material.getMaterial(existingType.name.removeSuffix("_POWDER")) ?: error("No material $glassType"), 1) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + override fun onLoad() { + displayHandler.update() } - val inventory = (getOutputBlock(sign.block).getState(false) as InventoryHolder).inventory - val output = getOutput(sign.block, fuel) + override fun onUnload() { + displayHandler.remove() + } - if (!LegacyItemUtils.canFit(inventory, output)) return + override fun handleRemoval() { + displayHandler.remove() + } - LegacyItemUtils.addToInventory(inventory, output) - PowerMachines.removePower(sign, 100) + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } - fuel.amount = fuel.amount - 1 - event.isBurning = false - event.burnTime = 50 - furnace.cookTime = (-1000).toShort() - event.isCancelled = false + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt index 8ba4a4ad4c..e24b81e188 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt @@ -19,6 +19,7 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED import org.bukkit.Material import org.bukkit.World @@ -176,10 +177,10 @@ abstract class PrinterMultiblock : Multiblock(), NewPoweredMultiblock Date: Wed, 9 Oct 2024 22:11:05 -0500 Subject: [PATCH 223/500] clarify function name --- .../type/farming/harvester/HarvesterMultiblock.kt | 8 ++++---- .../type/farming/planter/PlanterMultiblock.kt | 10 +++++----- .../type/printer/CarbonProcessorMultiblock.kt | 14 +++++++------- .../multiblock/type/printer/PrinterMultiblock.kt | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 2dfd157220..fdb4118492 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -130,7 +130,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun cancelWithStatus(status: Component, sleepTicks: Int) { + private fun sleepWithStatus(status: Component, sleepTicks: Int) { setStatus(status) tickingManager.sleep(sleepTicks) } @@ -140,7 +140,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I var broken = 0 val initialPower = powerStorage.getPower() - if (initialPower == 0) return cancelWithStatus(text("No Power", RED), 500) + if (initialPower == 0) return sleepWithStatus(text("No Power", RED), 500) val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) @@ -171,14 +171,14 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I val didNotFit = inventory.addItem(*drops) if (didNotFit.isNotEmpty()) { - cancelWithStatus(text("No Space", RED), 500) + sleepWithStatus(text("No Space", RED), 500) break } if (broken >= multiblock.tierNumber) break } - if (broken == 0) return cancelWithStatus(text("Sleeping", BLUE, ITALIC), 100) + if (broken == 0) return sleepWithStatus(text("Sleeping", BLUE, ITALIC), 100) powerStorage.removePower(broken * multiblock.powerPerCrop) setStatus(text("Working", GREEN)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 8073599e7a..ec349cc705 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -121,7 +121,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun cancelWithStatus(status: Component, sleepTicks: Int) { + private fun sleepWithStatus(status: Component, sleepTicks: Int) { setStatus(status) tickingManager.sleep(sleepTicks) } @@ -129,12 +129,12 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int override fun tick() { var planted = 0 val initialPower = powerStorage.getPower() - if (initialPower == 0) return cancelWithStatus(text("No Power", RED), 500) + if (initialPower == 0) return sleepWithStatus(text("No Power", RED), 500) val inventory: FurnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return tickingManager.sleep(800) - val seedItem = inventory.fuel ?: return cancelWithStatus(text("No Seeds", RED), 500) - val crop = Crop.findBySeed(seedItem.type) ?: return cancelWithStatus( text("Unknown Crop", RED), 1000) + val seedItem = inventory.fuel ?: return sleepWithStatus(text("No Seeds", RED), 500) + val crop = Crop.findBySeed(seedItem.type) ?: return sleepWithStatus( text("Unknown Crop", RED), 1000) val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) @@ -157,7 +157,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int if (planted >= multiblock.tierNumber) break } - if (planted == 0) return cancelWithStatus(text("Sleeping", BLUE, ITALIC), 100) + if (planted == 0) return sleepWithStatus(text("Sleeping", BLUE, ITALIC), 100) powerStorage.removePower(planted * multiblock.powerPerCrop) setStatus(text("Working", GREEN)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt index 70ea46f5d8..656c319639 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt @@ -110,30 +110,30 @@ object CarbonProcessorMultiblock : Multiblock(), NewPoweredMultiblock Date: Wed, 9 Oct 2024 23:15:52 -0500 Subject: [PATCH 224/500] update colors of planter / harvester tiers on signs --- .../ion/server/features/multiblock/old/Multiblocks.kt | 7 ++++--- .../type/farming/harvester/HarvesterMultiblock.kt | 6 +++--- .../type/farming/harvester/HarvesterMultiblockTier1.kt | 3 ++- .../type/farming/harvester/HarvesterMultiblockTier2.kt | 3 ++- .../type/farming/harvester/HarvesterMultiblockTier3.kt | 3 ++- .../multiblock/type/farming/planter/PlanterMultiblock.kt | 6 +++--- .../type/farming/planter/PlanterMultiblockTier1.kt | 3 ++- .../type/farming/planter/PlanterMultiblockTier2.kt | 3 ++- .../type/farming/planter/PlanterMultiblockTier3.kt | 3 ++- 9 files changed, 22 insertions(+), 15 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 6bcad49258..e83d2e8fef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -61,14 +61,17 @@ object Multiblocks : IonServerComponent() { } private fun initMultiblocks() { - // Furnace start + // Recipe system multis registerMultiblock(CentrifugeMultiblock) registerMultiblock(CompressorMultiblock) registerMultiblock(FabricatorMultiblock) registerMultiblock(CircuitfabMultiblock) registerMultiblock(PlatePressMultiblock) registerMultiblock(GasFurnaceMultiblock) + registerMultiblock(MissileLoaderMultiblock) + registerMultiblock(AmmoLoaderMultiblock) + // Furnace start registerMultiblock(GeneratorMultiblockTier1) registerMultiblock(GeneratorMultiblockTier2) registerMultiblock(GeneratorMultiblockTier3) @@ -78,8 +81,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(PowerFurnaceMultiblockTier3) registerMultiblock(StandardAmmoPressMultiblock) - registerMultiblock(AmmoLoaderMultiblock) - registerMultiblock(MissileLoaderMultiblock) registerMultiblock(GasCollectorMultiblock) registerMultiblock(VentMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index fdb4118492..32e2f96c45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -21,12 +21,12 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor.AQUA import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED +import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextDecoration.ITALIC import org.bukkit.Material import org.bukkit.World @@ -35,11 +35,11 @@ import org.bukkit.block.Sign import org.bukkit.block.data.Ageable import org.bukkit.persistence.PersistentDataAdapterContext -abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int) : Multiblock(), NewPoweredMultiblock { +abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { override val name: String = "harvester" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), - ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, AQUA)), + ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, tierColor)), null, null ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier1.kt index 96175e3ac4..23091bd64b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier1.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.harvester +import net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY import org.bukkit.Material -object HarvesterMultiblockTier1 : HarvesterMultiblock(Material.IRON_BLOCK, 1) { +object HarvesterMultiblockTier1 : HarvesterMultiblock(Material.IRON_BLOCK, 1, DARK_GRAY) { override val regionDepth: Int = 9 override val maxPower: Int = 50_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier2.kt index bf1e31f1b0..057552e745 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier2.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.harvester +import net.kyori.adventure.text.format.NamedTextColor.GOLD import org.bukkit.Material -object HarvesterMultiblockTier2 : HarvesterMultiblock(Material.GOLD_BLOCK, 2) { +object HarvesterMultiblockTier2 : HarvesterMultiblock(Material.GOLD_BLOCK, 2, GOLD) { override val regionDepth: Int = 15 override val maxPower: Int = 100_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier3.kt index 0b2f42a88b..097e700934 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblockTier3.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.harvester +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.Material -object HarvesterMultiblockTier3 : HarvesterMultiblock(Material.EMERALD_BLOCK, 3) { +object HarvesterMultiblockTier3 : HarvesterMultiblock(Material.EMERALD_BLOCK, 3, GREEN) { override val regionDepth: Int = 18 override val maxPower: Int = 200_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index ec349cc705..07ec5eb643 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -20,12 +20,12 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor.AQUA import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED +import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextDecoration.ITALIC import org.bukkit.Material import org.bukkit.World @@ -34,11 +34,11 @@ import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int) : Multiblock(), NewPoweredMultiblock { +abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { override val name: String = "planter" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), - ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, AQUA)), + ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, tierColor)), null, null ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier1.kt index 458e13f0e5..ede3f78385 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier1.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.planter +import net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY import org.bukkit.Material -object PlanterMultiblockTier1 : PlanterMultiblock(Material.IRON_BLOCK, 1) { +object PlanterMultiblockTier1 : PlanterMultiblock(Material.IRON_BLOCK, 1, DARK_GRAY) { override val regionDepth: Int = 9 override val maxPower: Int = 50_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier2.kt index 4fa318d74c..b886078794 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier2.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.planter +import net.kyori.adventure.text.format.NamedTextColor.GOLD import org.bukkit.Material -object PlanterMultiblockTier2 : PlanterMultiblock(Material.GOLD_BLOCK, 2) { +object PlanterMultiblockTier2 : PlanterMultiblock(Material.GOLD_BLOCK, 2, GOLD) { override val regionDepth: Int = 15 override val maxPower: Int = 100_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier3.kt index e8eb4c36ac..7683b2b76b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblockTier3.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type.farming.planter +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.Material -object PlanterMultiblockTier3 : PlanterMultiblock(Material.EMERALD_BLOCK, 3) { +object PlanterMultiblockTier3 : PlanterMultiblock(Material.EMERALD_BLOCK, 3, GREEN) { override val regionDepth: Int = 18 override val maxPower: Int = 200_000 } From f837977c3b9ada6236214701f6f0b99d6f186dee Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 10 Oct 2024 00:02:57 -0500 Subject: [PATCH 225/500] migrate auto crafters --- .../multiblock/MultiblockRegistration.kt | 8 +- .../features/multiblock/old/Multiblocks.kt | 11 +- .../type/autocrafter/AutoCrafterMultiblock.kt | 207 ++++++++++-------- .../autocrafter/AutoCrafterMultiblockTier1.kt | 6 +- .../autocrafter/AutoCrafterMultiblockTier2.kt | 6 +- .../autocrafter/AutoCrafterMultiblockTier3.kt | 4 +- .../multiblock/type/drills/DrillMultiblock.kt | 4 +- 7 files changed, 139 insertions(+), 107 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 5e0574873d..f656abebd9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -8,6 +8,9 @@ import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMu import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop +import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield10 import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield20 @@ -158,7 +161,10 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(DisposalMultiblock) - // Furnace powered multis + registerMultiblock(AutoCrafterMultiblockTier1) + registerMultiblock(AutoCrafterMultiblockTier2) + registerMultiblock(AutoCrafterMultiblockTier3) + registerMultiblock(CarbonPrinterMultiblock) registerMultiblock(TechnicalPrinterMultiblock) registerMultiblock(GlassPrinterMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index e83d2e8fef..0cad8744ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -11,9 +11,6 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockAccess.multibloc import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock -import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock @@ -90,10 +87,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(DecomposerMultiblock) registerMultiblock(ItemSplitterMultiblock) - - registerMultiblock(AutoCrafterMultiblockTier1) - registerMultiblock(AutoCrafterMultiblockTier2) - registerMultiblock(AutoCrafterMultiblockTier3) } private fun registerMultiblock(multiblock: Multiblock) { @@ -148,12 +141,12 @@ object Multiblocks : IonServerComponent() { } } - if (!multiblock.signMatchesStructureAsync(world, Vec3i(x, y, z), loadChunks)) continue; + if (!multiblock.signMatchesStructureAsync(world, Vec3i(x, y, z), loadChunks)) continue return multiblock } - return null; + return null } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 7ea6acf8e8..cfe963798b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -3,21 +3,38 @@ package net.horizonsend.ion.server.features.multiblock.type.autocrafter import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache -import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.common.utils.text.orEmpty +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.minecraft.world.item.crafting.CraftingInput +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.AQUA +import net.kyori.adventure.text.format.NamedTextColor.GRAY +import net.kyori.adventure.text.format.NamedTextColor.RED +import net.minecraft.world.entity.player.Player import net.minecraft.world.level.block.CrafterBlock import org.bukkit.Bukkit import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.craftbukkit.inventory.CraftItemStack as CBItemStack import org.bukkit.event.inventory.FurnaceBurnEvent @@ -28,10 +45,10 @@ import java.util.Optional private const val POWER_USAGE_PER_INGREDIENT = 15 abstract class AutoCrafterMultiblock( - tierText: String, + tierText: Component, private val tierMaterial: Material, private val iterations: Int, -) : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +) : Multiblock(), NewPoweredMultiblock { override val name = "autocrafter" override val requiredPermission: String? = "ion.multiblock.autocrafter" open val mirrored: Boolean = false @@ -92,77 +109,79 @@ abstract class AutoCrafterMultiblock( } } - override val signText: Array = createSignText( - line1 = "&aAuto", - line2 = "&6Crafter", - line3 = null, - line4 = tierText + override val signText: Array = arrayOf( + ofChildren(text("Auto ", GRAY), text("Crafter", AQUA)), + tierText, + null, + null ) - private fun getInput(sign: Sign): InventoryHolder? { - val forward = sign.getFacing().oppositeFace - val left = if (!mirrored) forward.rightFace.oppositeFace else forward.rightFace - val x = sign.x + forward.modX * 2 + left.modX * 2 - val y = sign.y + forward.modY * 2 + left.modY * 2 - val z = sign.z + forward.modZ * 2 + left.modZ * 2 - return getStateIfLoaded(sign.world, x, y, z) as? InventoryHolder - } + companion object { /* Items */ + val recipeCache: LoadingCache, Optional> = CacheBuilder.newBuilder().build( + CacheLoader.from { items -> + requireNotNull(items) + val level = Bukkit.getWorlds().first().minecraft + val input = CraftingInput.of(3, 3, items.map(CBItemStack::asNMSCopy)) - private fun getRecipeHolder(sign: Sign): InventoryHolder? { - val forward = sign.getFacing().oppositeFace - val x = sign.x + forward.modX * 2 - val y = sign.y + forward.modY * 2 - val z = sign.z + forward.modZ * 2 - return getStateIfLoaded(sign.world, x, y, z) as? InventoryHolder + // Get results for the recipe + CrafterBlock.getPotentialResults(level, input).map { recipe -> recipe.value.assemble(input, level.registryAccess()).asBukkitCopy() } + } + ) } - private fun getOutput(sign: Sign): InventoryHolder? { - val forward = sign.getFacing().oppositeFace - val right = if (!mirrored) forward.rightFace else forward.rightFace.oppositeFace - val x = sign.x + forward.modX * 2 + right.modX * 2 - val y = sign.y + forward.modY * 2 + right.modY * 2 - val z = sign.z + forward.modZ * 2 + right.modZ * 2 - return getStateIfLoaded(sign.world, x, y, z) as? InventoryHolder + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AutoCrafterEntity { + return AutoCrafterEntity(data, manager, this, x, y, z, world, structureDirection) } - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isCancelled = false - event.isBurning = false - - // Assume fail state - event.burnTime = 500 - - if (furnace.inventory.smelting?.type != Material.PRISMARINE_CRYSTALS) return - if (furnace.inventory.fuel?.type != Material.PRISMARINE_CRYSTALS) return - - val input: InventoryHolder = getInput(sign) ?: return - val recipeHolder: InventoryHolder = getRecipeHolder(sign) ?: return - val output: InventoryHolder = getOutput(sign) ?: return - - // material data of each item in the recipe holder, used as the crafting transportNetwork - val grid: List = recipeHolder.inventory.map { it } + class AutoCrafterEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: AutoCrafterMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, StatusMultiblock, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + private fun sleepWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } - val basePower = PowerMachines.getPower(sign, fast = true) + private fun getInput(): Inventory? = getInventory(-2, 0, 1) + private fun getRecipeHolder(): Inventory? = getInventory(0, 0, 1) + private fun getOutput(): Inventory? = getInventory(+2, 0, 1) - if (basePower < POWER_USAGE_PER_INGREDIENT) return + override fun tick() { + val inputInventory: Inventory = getInput() ?: return sleepWithStatus(text("Not Intact", RED), 500) + val recipeHolder: Inventory = getRecipeHolder() ?: return sleepWithStatus(text("Not Intact", RED), 500) + val output: Inventory = getOutput() ?: return sleepWithStatus(text("Not Intact", RED), 500) - var power = basePower + // material data of each item in the recipe holder, used as the crafting transportNetwork + val grid: List = recipeHolder.toList() - // result item of this recipe - val result: ItemStack = recipeCache[grid].orElse(null)?.clone() ?: return + val basePower = powerStorage.getPower() + if (basePower < POWER_USAGE_PER_INGREDIENT) return sleepWithStatus(text("Low Power", RED), 250) - val inputInventory = input.inventory + var power = basePower - val powerUsage = grid.filterNotNull().distinct().count() * POWER_USAGE_PER_INGREDIENT + // result item of this recipe + val result: ItemStack = recipeCache[grid].orElse(null)?.clone() ?: return sleepWithStatus(text("No Such Recipe", RED), 200) - // Success state - event.burnTime = 20 + val powerUsage = grid.filterNotNull().distinct().count() * POWER_USAGE_PER_INGREDIENT - try { - for (iteration in (1..iterations)) { - if (power < powerUsage) { - return - } + try { for (iteration in (1..multiblock.iterations)) { + if (power < powerUsage) return sleepWithStatus(text("Low Power", RED), 250) val removeSlots = mutableListOf() // can be multiple times per slot, so list, not set var requiredIngredients = 0 @@ -173,7 +192,7 @@ abstract class AutoCrafterMultiblock( // increment required ingredients to keep track of how many are needed, // and loop through the input inventory, // if an item's data matches the ingredient, - // flag that slot for removal,a + // flag that slot for removal, // increment matched ingredients, // and move on to the next ingredient ingredientLoop@ @@ -192,18 +211,16 @@ abstract class AutoCrafterMultiblock( } // stop iterating if not all of the ingredients were found - if (matchedIngredients != requiredIngredients) { - return - } + if (matchedIngredients != requiredIngredients) return - val remaining: HashMap = output.inventory.addItem(result) + val remaining: HashMap = output.addItem(result) if (remaining.isNotEmpty()) { val added = result.amount - remaining.values.sumOf { it.amount } check(added >= 0) - if (added > 0) { - output.inventory.removeItem(result.clone().apply { amount = added }) - } + + if (added > 0) output.removeItem(result.clone().apply { amount = added }) + return } @@ -232,28 +249,38 @@ abstract class AutoCrafterMultiblock( for (index in removeSlots) { // since AFAIK recipes only call for one item per ingredient, just decrement the amount // it will automatically remove the item if the amount hits 0 - input.inventory.getItem(index)!!.amount-- + inputInventory.getItem(index)!!.amount-- + } + } } finally { + if (basePower != power) { + powerStorage.setPower(power) + } else { + // Nothing crafted, could be temporary resource shortage, pause for shorter time period + sleepWithStatus(result.displayName(), 200) } - } - } finally { - if (basePower != power) PowerMachines.setPower(sign, power) else { - // Nothing crafted, could be temporary resource shortage, pause for shorter time period - event.burnTime = 200 } } - } - companion object { - private val recipeCache: LoadingCache, Optional> = CacheBuilder.newBuilder().build( - CacheLoader.from { items -> - requireNotNull(items) - val level = Bukkit.getWorlds().first().minecraft - val input = CraftingInput.of(3, 3, items.map(CBItemStack::asNMSCopy)) + override fun onLoad() { + displayHandler.update() + } - // Get results for the recipe - CrafterBlock.getPotentialResults(level, input).map { recipe -> recipe.value.assemble(input, level.registryAccess()).asBukkitCopy() } - } - ) + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + multiblock.signText.withIndex().forEach { sign.front().line(it.index, it.value.orEmpty()) } + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier1.kt index f3ce5df295..07c4ca0226 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier1.kt @@ -1,11 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.type.autocrafter +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY import org.bukkit.Material -object AutoCrafterMultiblockTier1 : AutoCrafterMultiblock("&8Tier 1", Material.IRON_BLOCK, iterations = 2) { +object AutoCrafterMultiblockTier1 : AutoCrafterMultiblock(text("Tier 1", DARK_GRAY), Material.IRON_BLOCK, iterations = 2) { override val maxPower: Int = 200_000 } -object AutoCrafterMultiblockTier1Mirrored : AutoCrafterMultiblockMirrored("&8Tier 1", Material.IRON_BLOCK, iterations = 2) { +object AutoCrafterMultiblockTier1Mirrored : AutoCrafterMultiblockMirrored(text("Tier 1", DARK_GRAY), Material.IRON_BLOCK, iterations = 2) { override val maxPower: Int = 200_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier2.kt index 2ee6ddbbc2..70e66332af 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier2.kt @@ -1,11 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.type.autocrafter +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.YELLOW import org.bukkit.Material -object AutoCrafterMultiblockTier2 : AutoCrafterMultiblock("&eTier 2", Material.GOLD_BLOCK, iterations = 4) { +object AutoCrafterMultiblockTier2 : AutoCrafterMultiblock(text("Tier 2", YELLOW), Material.GOLD_BLOCK, iterations = 4) { override val maxPower: Int = 400_000 } -object AutoCrafterMultiblockTier2Mirrored : AutoCrafterMultiblockMirrored("&eTier 2", Material.GOLD_BLOCK, iterations = 4) { +object AutoCrafterMultiblockTier2Mirrored : AutoCrafterMultiblockMirrored(text("Tier 2", YELLOW), Material.GOLD_BLOCK, iterations = 4) { override val maxPower: Int = 400_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt index 0b8224d79c..0d23140c36 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.type.autocrafter +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.AQUA import org.bukkit.Material -object AutoCrafterMultiblockTier3 : AutoCrafterMultiblock("&bTier 3", Material.DIAMOND_BLOCK, iterations = 6) { +object AutoCrafterMultiblockTier3 : AutoCrafterMultiblock(text("Tier 3", AQUA), Material.DIAMOND_BLOCK, iterations = 6) { override val maxPower: Int = 600_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 00b73db744..383e694ff3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -129,8 +129,8 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M y: Int, z: Int, world: World, - signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 5) override val userManager: UserManager = UserManager(data, persistent = true) From bd5529fc5fb9ef3a987a618f724c15abbe691fd0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 10 Oct 2024 00:06:41 -0500 Subject: [PATCH 226/500] add status for full auto crafter --- .../multiblock/type/autocrafter/AutoCrafterMultiblock.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index cfe963798b..2a456a2e62 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -221,7 +221,7 @@ abstract class AutoCrafterMultiblock( if (added > 0) output.removeItem(result.clone().apply { amount = added }) - return + return sleepWithStatus(text("Output Full", RED), 100) } power -= powerUsage From 707c7cd66efda8f258dfccbec93dab2a9b77104b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 11 Oct 2024 01:54:49 -0500 Subject: [PATCH 227/500] rewrite decomposers and also node relationships I guess --- .../ion/common/utils/text/Formatting.kt | 3 + .../server/features/machine/DecomposeTask.kt | 171 +++++++++++++++++ .../machine/decomposer/DecomposeTask.kt | 175 ------------------ .../machine/decomposer/Decomposers.kt | 141 -------------- .../multiblock/MultiblockRegistration.kt | 3 + .../multiblock/entity/MultiblockEntity.kt | 4 +- .../features/multiblock/old/Multiblocks.kt | 3 - .../type/autocrafter/AutoCrafterMultiblock.kt | 7 +- .../type/misc/DecomposerMultiblock.kt | 144 +++++++++++++- .../transport/node/NodeRelationship.kt | 7 +- .../features/transport/node/RelationHolder.kt | 4 +- .../transport/node/manager/NodeManager.kt | 8 +- .../miscellaneous/registrations/Components.kt | 5 +- 13 files changed, 329 insertions(+), 346 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/DecomposeTask.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt index 163fd52940..8732869a39 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.common.database.schema.nations.Nation import net.horizonsend.ion.common.utils.text.colors.HEColorScheme import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_DARK_GRAY import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_LIGHT_GRAY +import net.kyori.adventure.audience.Audience import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text @@ -297,3 +298,5 @@ fun formatException(throwable: Throwable): Component { .hoverEvent(text(stackTrace)) .clickEvent(ClickEvent.copyToClipboard(stackTrace)) } + +fun button(text: Component, onClick: (Audience) -> Unit): Component = bracketed(text).clickEvent(ClickEvent.callback(onClick)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt new file mode 100644 index 0000000000..c4fa8b1917 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt @@ -0,0 +1,171 @@ +package net.horizonsend.ion.server.features.machine + +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.serverError +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock +import net.horizonsend.ion.server.features.ores.OldOreData +import net.horizonsend.ion.server.features.starship.isFlyable +import net.horizonsend.ion.server.miscellaneous.utils.nms +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import org.bukkit.Material.AIR +import org.bukkit.SoundCategory +import org.bukkit.block.Block +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.scheduler.BukkitRunnable + +class DecomposeTask( + private val entity: DecomposerMultiblock.DecomposerEntity, + private val maxWidth: Int, + private val maxHeight: Int, + private val maxDepth: Int +) : BukkitRunnable() { + private var totalBlocksBroken = 0 + + private var currentBlock: Block = entity.regionOrigin + + override fun run() { + try { + if (breakStrip()) return + } catch (exception: Exception) { + entity.userManager.getUserPlayer()?.serverError("Decomposer encountered server error. Please contact staff.") + exception.printStackTrace() + cancel() + return + } + + cancel() + } + + override fun cancel() { + super.cancel() + + entity.userManager.getUserPlayer()?.information("Decomposer broke $totalBlocksBroken blocks.") + entity.userManager.clear() + entity.currentTask = null + } + + /** returns whether it should be cancelled */ + private fun breakStrip(): Boolean { + val player = entity.userManager.getUserPlayer() ?: return false + + if (!entity.isIntact(checkSign = true)) { + player.userError("Decomposer destroyed.") + return false + } + + val storage = entity.getStorage() ?: return run { + player.userError("Decomposer storage missing.") + false + } + + var power = entity.powerStorage.getPower() + var iterationBroken = 0 + var success = true + + while (iterationBroken < DecomposerMultiblock.BLOCKS_PER_SECOND) { + // If decompose task is cancelled + if (isCancelled) break + + if (!currentBlock.location.isChunkLoaded) { + moveForward() + continue + } + + if (currentBlock.type.isAir) { + moveForward() + continue + } + + if (!BlockBreakEvent(currentBlock, player).callEvent()) { + moveForward() + continue + } + + if (power < 10) { + player.userError("Decomposer out of power!") + success = false + break + } + + power -= 10 + + val blockData = currentBlock.blockData + val customBlock = CustomBlocks.getByBlockData(blockData) + + // get drops BEFORE breaking + var drops: List = currentBlock.drops.toList() + + var customOre = false + OldOreData.entries.forEach { ore -> if (ore.blockData == (customBlock?.blockData ?: false)) customOre = true } + + if (customBlock != null && !customOre) drops = customBlock.drops.getDrops(null, false).toList() + + currentBlock.setType(AIR, false) + + if (isFlyable(blockData.nms)) { + val remaining: HashMap = storage.addItem(*drops.toTypedArray()) + + if (remaining.any()) { + for (drop in drops) currentBlock.world.dropItemNaturally(entity.getSignLocation(), drop) + + player.userError("Decomposer out of space, dropping items and cancelling decomposition.") + success = false + break + } + } + + totalBlocksBroken++ + iterationBroken++ + } + + entity.powerStorage.setPower(power) + + for (soundPlayer in entity.world.players) { + if (soundPlayer.location.distance(currentBlock.location) >= maxWidth * 1.5) continue + + soundPlayer.playSound( + soundPlayer.location, + currentBlock.blockData.soundGroup.breakSound, + SoundCategory.BLOCKS, + 0.5f, + 1.0f + ) + } + + return success + } + + private fun moveForward(): Boolean { + val next = getNextBlock(currentBlock) ?: return false + currentBlock = next + return true + } + + private fun getNextBlock(block: Block): Block? { + val origin = entity.regionOrigin + val right = entity.structureDirection.rightFace + + // + 1 to get one block inside the frame + val currentWidth = (right.modX * (block.x - origin.x)) + (right.modZ * (block.z - origin.z)) + 1 + val currentHeight = block.y - origin.y + 1 + val currentDepth = (entity.structureDirection.modX * (block.x - origin.x)) + (entity.structureDirection.modZ * (block.z - origin.z)) + 1 + + // If possible move forward + return if (currentDepth < maxDepth) { + // If can't move forward, start next row + entity.getBlockRelative(currentWidth, currentHeight, currentDepth + 1) + } else if (currentHeight < maxHeight) { + // If can't move up, start new column + entity.getBlockRelative(currentWidth, currentHeight + 1, 1) + } else if (currentWidth < maxWidth) { + // Try move right, if can't, it's done + entity.getBlockRelative(currentWidth + 1, 1, 1) + } else { + cancel() + null + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/DecomposeTask.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/DecomposeTask.kt deleted file mode 100644 index 7f40302219..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/DecomposeTask.kt +++ /dev/null @@ -1,175 +0,0 @@ -package net.horizonsend.ion.server.features.machine.decomposer - -import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.serverError -import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock -import net.horizonsend.ion.server.features.ores.OldOreData -import net.horizonsend.ion.server.features.starship.isFlyable -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.nms -import org.bukkit.Bukkit -import org.bukkit.Location -import org.bukkit.Material -import org.bukkit.SoundCategory -import org.bukkit.block.BlockFace -import org.bukkit.block.Sign -import org.bukkit.block.data.BlockData -import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.scheduler.BukkitRunnable -import java.util.UUID - -/** - * @param width Iterated first, - * @param startWidthOffset Start offset down width from 0. - * @param height Iterated second, - * @param length Iterated third, - * @param right direction of width - * @param up direction up height - * @param forward direction of length - * */ -class DecomposeTask( - private val signLoc: Location, - private val width: Int, - private var startWidthOffset: Int, - private val height: Int, - private val length: Int, - private val origin: Location, - private val right: BlockFace, - private val up: BlockFace, - private val forward: BlockFace, - private val playerID: UUID, - private val multiblock: DecomposerMultiblock -) : BukkitRunnable() { - private var blocksBroken = 0 - - override fun run() { - try { - if (breakStrip()) { - return - } - } catch (exception: Exception) { - Bukkit.getPlayer(playerID) - ?.serverError( - "Decomposer encountered server error. Please contact staff." - ) - exception.printStackTrace() - cancel() - return - } - - cancel() - } - - override fun cancel() { - super.cancel() - - Decomposers.busySigns.remove(signLoc) - Bukkit.getPlayer(playerID) - ?.information("Decomposer broke $blocksBroken blocks.") - } - - private fun breakStrip(): Boolean { - if (startWidthOffset >= width) return false - - val player = Bukkit.getPlayer(playerID) ?: return false - - val signBlock = getBlockIfLoaded(signLoc.world, signLoc.blockX, signLoc.blockY, signLoc.blockZ) ?: return false - val sign = signBlock.state as? Sign ?: return false - - if (!multiblock.signMatchesStructure(sign, loadChunks = false)) { - return false - } - - val storage = DecomposerMultiblock.getStorage(sign) - val power = PowerMachines.getPower(sign, fast = true) - - var firstBlock: BlockData? = null - - for (offsetUp: Int in 0 until height) { - for (offsetForward: Int in 0 until length) { - val newLocation = origin.clone() - .add(right.direction.multiply(startWidthOffset)) - .add(up.direction.multiply(offsetUp)) - .add(forward.direction.multiply(offsetForward)) - .toBlockLocation() - - if (!newLocation.isChunkLoaded) { - continue - } - - val block = newLocation.block - val blockData = block.blockData - val customBlock = CustomBlocks.getByBlock(block) - - if (blockData.material.isAir) continue - - val testEvent = BlockBreakEvent(block, player) - testEvent.isDropItems = false - - if (!testEvent.callEvent()) continue - - if (firstBlock == null) { firstBlock = blockData } - - if (power < 10) { - player.userError("Decomposer out of power!") - return false - } - - PowerMachines.removePower(sign, 10) - - // get drops BEFORE breaking - var drops: List = block.drops.toList() - - var customOre = false - OldOreData.entries.forEach { ore -> if (ore.blockData == (customBlock?.blockData ?: false)) customOre = true } - - if (customBlock != null && !customOre) drops = customBlock.drops.getDrops(null, false).toList() - - block.setType(Material.AIR, false) - - blocksBroken++ - - if (isFlyable(blockData.nms)) { - val remaining: HashMap = storage.addItem(*drops.toTypedArray()) - if (remaining.any()) { - for (drop in drops) { - sign.world.dropItemNaturally(sign.location.toCenterLocation(), drop) - } - - player.userError( - "Decomposer out of space, dropping items and cancelling decomposition." - ) - return false - } - } - } - } - - firstBlock?.let { - val stripCenter: Location = origin.clone() - .add(right.direction.multiply(startWidthOffset)) - .add(up.direction.multiply(height / 2.0)) - .add(forward.direction.multiply(length / 2.0)) - .toBlockLocation() - - for (soundPlayer in origin.world.players) { - if (soundPlayer.location.distance(stripCenter) >= width * 1.5) continue - soundPlayer.playSound( - soundPlayer.location, - firstBlock.soundGroup.breakSound, - SoundCategory.BLOCKS, - 0.5f, - 1.0f - ) - } - } - - startWidthOffset++ - - return true - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt deleted file mode 100644 index bede26c575..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/decomposer/Decomposers.kt +++ /dev/null @@ -1,141 +0,0 @@ -package net.horizonsend.ion.server.features.machine.decomposer - -import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.success -import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock -import net.horizonsend.ion.server.features.player.CombatTimer -import net.horizonsend.ion.server.miscellaneous.utils.CHISELED_TYPES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import org.bukkit.Location -import org.bukkit.block.BlockFace -import org.bukkit.block.Sign -import org.bukkit.event.block.Action -import org.bukkit.event.player.PlayerInteractEvent -import kotlin.math.max - -object Decomposers : IonServerComponent() { - val busySigns = mutableMapOf() - - private const val MAX_LENGTH = 100 - private const val BLOCKS_PER_SECOND = 1000 - private val FRAME_MATERIAL = CHISELED_TYPES - - fun onClick(event: PlayerInteractEvent) { - val sign = event.clickedBlock?.state as? Sign ?: return - val signLoc = sign.location - - if (event.action == Action.RIGHT_CLICK_BLOCK) { - val forward = sign.getFacing().oppositeFace - val up = BlockFace.UP - val right = forward.rightFace - - val origin: Location = signLoc.clone() - .add(forward.direction.multiply(2)) - .add(up.direction) - .add(right.direction) - - val frameOrigin: Location = signLoc.clone().add(forward.direction) - - val width = getDimension(frameOrigin, right) - val height = getDimension(frameOrigin, up) - val length = getDimension(frameOrigin, forward) - - val area = height * length - val delay = max(10L, area / BLOCKS_PER_SECOND * 20L) - - val offset = calculateOffset(origin, width, height, length, right, up, forward) - - if (length == 0 || width == 0 || height == 0) return event.player.userError("Decomposer has zero volume! Make sure the chiseled blocks extend to the right of the multiblock.") - - if (CombatTimer.isPvpCombatTagged(event.player)) { - event.player.userError("Cannot enable decomposers while in combat") - return - } - -// if (offset > width) return event.player.userError("Decomposer empty!") - - val task = DecomposeTask( - signLoc, - width, - offset, - height, - length, - origin, - right, - up, - forward, - event.player.uniqueId, - DecomposerMultiblock - ) - - if (busySigns.containsKey(signLoc)) { - event.player.userError("Decomposer in use") - return - } - - task.runTaskTimer(IonServer, delay, delay) - - event.player.success("Started Decomposer") - - busySigns[signLoc] = task - } else { - (busySigns[signLoc] ?: return event.player.information("Decomposer not in use")).cancel() - - event.player.information("Cancelled running decomposer") - } - } - - private fun getDimension(origin: Location, direction: BlockFace): Int { - var dimension = 0 - var tempBlock = origin.block - - while (dimension < MAX_LENGTH) { - tempBlock = tempBlock.getRelativeIfLoaded(direction) - ?: return dimension - - if (!FRAME_MATERIAL.contains(tempBlock.type)) { - return dimension - } - - dimension++ - } - - return dimension - } - - private fun calculateOffset( - origin: Location, - width: Int, - height: Int, - length: Int, - right: BlockFace, - up: BlockFace, - forward: BlockFace - ): Int { - val world = origin.world - - for (offsetWidth: Int in 0 until height) { - for (offsetForward: Int in 0 until length) { - for (offsetUp: Int in 0 until width) { - val loc = origin.clone() - - loc.add(up.direction.multiply(offsetUp)) - loc.add(forward.direction.multiply(offsetForward)) - loc.add(right.direction.multiply(offsetWidth)) - - val block = getNMSBlockSateSafe(world, Vec3i(loc)) - if (block?.isAir == false) return offsetWidth - } - } - } - - return width + 1 - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index f656abebd9..0baa3f1856 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -33,6 +33,7 @@ import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTa import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock @@ -277,6 +278,8 @@ object MultiblockRegistration : IonServerComponent() { // Machine registerMultiblock(ShipFactoryMultiblock) + registerMultiblock(DecomposerMultiblock) + // Misc registerMultiblock(DisconnectedDockingTubeMultiblock) registerMultiblock(ConnectedDockingTubeMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index f93e96ddbf..77471eb6bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -127,9 +127,11 @@ abstract class MultiblockEntity( * Gets the sign of this multiblock **/ fun getSign(): Sign? { - return getSignFromOrigin(world ,vec3i, structureDirection).state as? Sign + return getSignFromOrigin(world, vec3i, structureDirection).state as? Sign } + fun getSignLocation() = getSignFromOrigin(world, vec3i, structureDirection).location + /** * Gets the origin block of this multiblock **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 0cad8744ad..0f9d9adaeb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -20,7 +20,6 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMu import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 @@ -84,8 +83,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(GasPowerPlantMultiblock) // Furnace end - registerMultiblock(DecomposerMultiblock) - registerMultiblock(ItemSplitterMultiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 2a456a2e62..0075aba1fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -24,12 +24,11 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.text.Component -import net.minecraft.world.item.crafting.CraftingInput import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.AQUA import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.RED -import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.crafting.CraftingInput import net.minecraft.world.level.block.CrafterBlock import org.bukkit.Bukkit import org.bukkit.Material @@ -37,8 +36,6 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.craftbukkit.inventory.CraftItemStack as CBItemStack -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.InventoryHolder import org.bukkit.inventory.ItemStack import java.util.Optional @@ -176,7 +173,7 @@ abstract class AutoCrafterMultiblock( var power = basePower // result item of this recipe - val result: ItemStack = recipeCache[grid].orElse(null)?.clone() ?: return sleepWithStatus(text("No Such Recipe", RED), 200) + val result: ItemStack = recipeCache[grid].orElse(null)?.clone() ?: return sleepWithStatus(text("Invalid Recipe", RED), 200) val powerUsage = grid.filterNotNull().distinct().count() * POWER_USAGE_PER_INGREDIENT diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt index c94ca7428a..9ca03bea63 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt @@ -1,18 +1,42 @@ package net.horizonsend.ion.server.features.multiblock.type.misc -import net.horizonsend.ion.server.features.machine.decomposer.Decomposers +import net.horizonsend.ion.common.extensions.success +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.button +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay +import net.horizonsend.ion.server.features.machine.DecomposeTask import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity.UserManager +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.listener.misc.ProtectionListener.isRegionDenied +import net.horizonsend.ion.server.miscellaneous.utils.CHISELED_TYPES +import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.RED +import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player +import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryHolder -object DecomposerMultiblock : Multiblock(), PowerStoringMultiblock, InteractableMultiblock { +object DecomposerMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { override val maxPower: Int = 75_000 override val name: String = "decomposer" override val signText = createSignText( @@ -27,11 +51,113 @@ object DecomposerMultiblock : Multiblock(), PowerStoringMultiblock, Interactable at(0, -1, -1).anyPipedInventory() } - fun getStorage(sign: Sign): Inventory { - return (sign.block.getRelative(BlockFace.DOWN).state as InventoryHolder).inventory + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + if (event.action != Action.RIGHT_CLICK_BLOCK) return + + val entity = getMultiblockEntity(sign) ?: return + entity.handleClick(player) } - override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { - Decomposers.onClick(event) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): DecomposerEntity { + return DecomposerEntity(data, manager, x, y, z, world, structureDirection) + } + + const val MAX_LENGTH = 100 + const val BLOCKS_PER_SECOND = 100 + private val FRAME_MATERIAL = CHISELED_TYPES + + class DecomposerEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, DecomposerMultiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock, UserManagedMultiblockEntity { + override val multiblock = DecomposerMultiblock + override val powerStorage: PowerStorage = loadStoredPower(data) + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + override val userManager: UserManager = UserManager(data, false) + + val regionOrigin get() = getBlockRelative(1, 1, 1) + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + var currentTask: DecomposeTask? = null + + fun handleClick(player: Player) { + if (userManager.currentlyUsed()) { + if (userManager.getUserId() != player.uniqueId) return player.userError("Decomposer in use!") + return player.sendMessage(ofChildren(text("Would you like to cancel?" ), button(text("Confirm", RED)) { currentTask?.cancel() })) + } + + if (isRegionDenied(player, getOrigin().location)) return player.userError("You can't use that here!") + if (powerStorage.getPower() < 10) return player.userError("Insufficient Power!") + + val width = checkArm(structureDirection.rightFace) + val height = checkArm(BlockFace.UP) + val depth = checkArm(structureDirection) + + if (width == 0 || height == 0 || depth == 0) { + player.userError("Invalid decomposer! It contains zero blocks. Build frames with chiseled blocks to the right to outline the region.") + return + } + + userManager.setUser(player) + currentTask = DecomposeTask( + this, + width, + height, + depth, + ) + + currentTask?.runTaskTimer(IonServer, 20L, 20L) + + player.success("Started Decomposer") + } + + private fun checkArm(direction: BlockFace): Int { + var dimension = 0 + var tempBlock = getOrigin() + + while (dimension < MAX_LENGTH) { + tempBlock = tempBlock.getRelativeIfLoaded(direction) ?: return dimension + + if (!FRAME_MATERIAL.contains(tempBlock.type)) { + return dimension + } + + dimension++ + } + + return dimension + } + + fun getStorage() = getInventory(0, -1, -1) + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt index 48d9732321..27d522ba9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.node +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.BlockFace /** @@ -7,6 +8,8 @@ import org.bukkit.block.BlockFace * The information contains whether they may transfer to / from each other, from each side **/ data class NodeRelationship( + val position: BlockKey, + val otherPosition: BlockKey, val holder: TransportNode, val other: TransportNode, val offset: BlockFace, @@ -16,8 +19,8 @@ data class NodeRelationship( * Break the relation between the two nodes **/ fun breakUp() { - holder.removeRelationship(other) - other.removeRelationship(holder) + holder.relationHolder.raw()[position]?.remove(this) + other.relationHolder.raw()[otherPosition]?.remove(this) holder.refreshTransferCache() other.refreshTransferCache() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt index b4b551ae0f..f91b936b8e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt @@ -37,9 +37,9 @@ class RelationHolder(val node: TransportNode) { val otherToHolder = other.isTransferableTo(node) // Add relation from this node to the other - add(holderPosition, NodeRelationship(node, other, nodeTwoOffset, holderToOther)) + add(holderPosition, NodeRelationship(holderPosition, otherPosition, node, other, nodeTwoOffset, holderToOther)) // Add relation from the other to this - other.relationHolder.add(otherPosition, NodeRelationship(other, node, nodeTwoOffset.oppositeFace, otherToHolder)) + other.relationHolder.add(otherPosition, NodeRelationship(otherPosition, holderPosition, other, node, nodeTwoOffset.oppositeFace, otherToHolder)) node.refreshTransferCache() other.refreshTransferCache() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 51c15109e9..986ca4c70b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.node.manager -import kotlinx.coroutines.runBlocking import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.transport.node.util.NodeFactory +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -130,7 +130,7 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { **/ fun onUnload() { // Break cross chunk relations - breakAllRelations() + Tasks.async { breakAllRelations() } } /** @@ -147,8 +147,8 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { **/ open fun finalizeNodes() {} - fun breakAllRelations() { - runBlocking { nodes.values.forEach { it.clearRelations() } } + private fun breakAllRelations() { + nodes.values.forEach { it.clearRelations() } } fun getNode(x: Int, y: Int, z: Int, allowNeighborChunks: Boolean = true): TransportNode? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 0c99563242..0af953f440 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -12,10 +12,10 @@ import net.horizonsend.ion.server.features.chat.ChatChannel import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities import net.horizonsend.ion.server.features.client.display.HudIcons +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.MultiBlockDisplay import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.type.weapon.sword.SwordListener -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.economy.bazaar.Bazaars import net.horizonsend.ion.server.features.economy.bazaar.Merchants import net.horizonsend.ion.server.features.economy.cargotrade.CrateRestrictions @@ -30,7 +30,6 @@ import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.machine.AntiAirCannons import net.horizonsend.ion.server.features.machine.AreaShields import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.machine.decomposer.Decomposers import net.horizonsend.ion.server.features.misc.AutoRestart import net.horizonsend.ion.server.features.misc.CapturableStationCache import net.horizonsend.ion.server.features.misc.GameplayTweaks @@ -102,7 +101,6 @@ import net.horizonsend.ion.server.features.tutorial.Tutorials import net.horizonsend.ion.server.features.waypoint.WaypointManager import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.data.DataFixers -import net.horizonsend.ion.server.features.world.environment.mobs.CustomMobSpawning import net.horizonsend.ion.server.listener.misc.WorldEditListener import net.horizonsend.ion.server.miscellaneous.registrations.legacy.CustomRecipes import net.horizonsend.ion.server.miscellaneous.utils.Notify @@ -201,7 +199,6 @@ val components: List = listOf( StarshipDealers, TutorialNPCs, ShipKillXP, - Decomposers, ChatChannel.ChannelActions, ChannelSelections, From f64cbcceef9ca9e94351a9958c5dc20ccd1ba4c8 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 11 Oct 2024 02:12:34 -0500 Subject: [PATCH 228/500] remove 90% of the old multiblock code --- .../server/features/machine/PowerMachines.kt | 14 +- .../features/multiblock/old/Multiblocks.kt | 183 +----------------- .../server/features/transport/old/Wires.kt | 4 +- .../server/listener/misc/FurnaceListener.kt | 5 +- 4 files changed, 6 insertions(+), 200 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt index 6756d052fe..5fb6f31fa5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/PowerMachines.kt @@ -2,8 +2,6 @@ package net.horizonsend.ion.server.features.machine import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.old.Multiblocks -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor @@ -62,13 +60,7 @@ object PowerMachines : IonServerComponent() { @JvmOverloads fun setPower(sign: Sign, power: Int, fast: Boolean = true): Int { - val correctedPower: Int = if (!fast) { - val multiblock = (Multiblocks[sign] ?: return 0) as? PowerStoringMultiblock ?: return 0 - power.coerceIn(0, multiblock.maxPower) - } else { - power.coerceAtLeast(0) - } - + val correctedPower: Int = power.coerceAtLeast(0) if (!sign.persistentDataContainer.has(NamespacedKeys.MULTIBLOCK)) return power sign.persistentDataContainer.set(NamespacedKeys.POWER, PersistentDataType.INTEGER, correctedPower) @@ -79,10 +71,6 @@ object PowerMachines : IonServerComponent() { @JvmOverloads fun getPower(sign: Sign, fast: Boolean = true): Int { - if (!fast && Multiblocks[sign] !is PowerStoringMultiblock) { - return 0 - } - return sign.persistentDataContainer.get(NamespacedKeys.POWER, PersistentDataType.INTEGER) ?: return setPower(sign, 0) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 0f9d9adaeb..bc145a67eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -1,13 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.old -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.command.misc.MultiblockCommand.setupCommand import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockAccess.multiblockCoroutineScope import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock @@ -27,35 +21,8 @@ import net.horizonsend.ion.server.features.multiblock.type.power.generator.Gener import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 -import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState -import net.horizonsend.ion.server.features.progression.achievements.Achievement -import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.World -import org.bukkit.block.Sign -import org.bukkit.block.sign.Side -import org.bukkit.entity.Player -import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority -import org.bukkit.event.block.Action -import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.EquipmentSlot -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import java.util.UUID object Multiblocks : IonServerComponent() { - private val multiblocks: MutableMap = mutableMapOf() - - override fun onEnable() { - initMultiblocks() - - log.info("Loaded ${multiblocks.size} multiblocks") - } - private fun initMultiblocks() { // Recipe system multis registerMultiblock(CentrifugeMultiblock) @@ -86,153 +53,5 @@ object Multiblocks : IonServerComponent() { registerMultiblock(ItemSplitterMultiblock) } - private fun registerMultiblock(multiblock: Multiblock) { - val name = multiblock.javaClass.simpleName ?: throw IllegalArgumentException("Provided anonymous multiblock class!") - - if (multiblocks.containsKey(name)) { - throw IllegalArgumentException("Attempted to register duplicate multiblock name! Exisitng: ${multiblocks[name]}, new: $multiblock") - } - - multiblocks[name] = multiblock - } - - /** - * Map of world UUIDs to a map of block keys to Multiblock types - * - * - world - * |- blockKey to Multiblock - **/ - private val multiblockLocationCache: MutableMap> = Object2ObjectOpenHashMap() - - /** - * Get a multiblock from the sign - **/ - operator fun get(sign: Sign, checkStructure: Boolean = true, loadChunks: Boolean = false) = runBlocking { - getFromSignPosition(sign.world, sign.x, sign.y, sign.z, checkStructure, loadChunks) - } - - /** - * Checks against the multiblock cache for a multiblock at a position - * - * Only considers detected multiblocks - **/ - suspend fun getFromSignPosition(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean, loadChunks: Boolean = false): Multiblock? { - val block = world.getBlockAt(x, y, z) - - val cached = checkCache(world, x, y, z, checkStructure, loadChunks) - - if (cached != null) return cached - - val sign = getBukkitBlockState(block, loadChunks) as? Sign ?: return null - - for ((name, multiblock) in multiblocks) { - if (!matchesPersistentDataContainer(sign.persistentDataContainer, multiblock)) { - if (!multiblock.matchesSign(sign.getSide(Side.FRONT).lines())) continue else Tasks.sync { - sign.persistentDataContainer.set( - NamespacedKeys.MULTIBLOCK, - PersistentDataType.STRING, - name - ) - sign.isWaxed = true - sign.update(false, false) - } - } - - if (!multiblock.signMatchesStructureAsync(world, Vec3i(x, y, z), loadChunks)) continue - - return multiblock - } - - return null - } - - /** - * Checks against the multiblock cache for a multiblock at a position - **/ - private suspend fun checkCache(world: World, x: Int, y: Int, z: Int, checkStructure: Boolean, loadChunks: Boolean): Multiblock? { - val worldCache = multiblockLocationCache[world.uid] ?: return null - - val key = toBlockKey(x, y, z) - - val possibleMultiblock = worldCache[key] ?: return null - - if (checkStructure && !possibleMultiblock.signMatchesStructureAsync(world, Vec3i(x, y, z), loadChunks)) return null - - return possibleMultiblock - } - - private fun matchesPersistentDataContainer(persistentDataContainer: PersistentDataContainer, multiblock: Multiblock): Boolean { - val value = persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING) ?: return false - - return value == multiblock::class.simpleName - } - - /** - * The check for when someone right-clicks an undetected multiblock - **/ - @EventHandler(priority = EventPriority.HIGHEST) - fun tryDetectMultiblock(event: PlayerInteractEvent) = multiblockCoroutineScope.launch { - if (event.hand != EquipmentSlot.HAND || event.action != Action.RIGHT_CLICK_BLOCK) return@launch - - val clickedBlock = event.clickedBlock ?: return@launch - val sign = getBukkitBlockState(clickedBlock, false) as? Sign ?: return@launch - - // Don't bother checking detected multiblocks - if (sign.persistentDataContainer.has(NamespacedKeys.MULTIBLOCK)) return@launch - - var lastMatch: Multiblock? = null - val player = event.player - - if (!player.hasPermission("starlegacy.multiblock.detect")) { - player.userError("You don't have permission to detect multiblocks!") - return@launch - } - - // Check all multiblocks with a matching undetected sign - for ((_, multiblock) in multiblocks.filterValues { it.matchesUndetectedSign(sign) }) { - // And is built properly - if (multiblock.signMatchesStructure(sign, particles = true)) { - // Check permissions here because different tiers might have the same text - multiblock.requiredPermission?.let { - if (!player.hasPermission(it)) player.userError("You don't have permission to use that multiblock!") - return@launch - } - - // Update everything that needs to be done sync - createNewMultiblock(multiblock, sign, event.player) - - return@launch - } - - // Store the multi that last matched sign text - lastMatch = multiblock - } - - if (lastMatch != null) { - player.userError("Improperly built ${lastMatch.name}. Make sure every block is correctly placed!") - - // Prompt the help command - setupCommand(player, sign, lastMatch) - } - } - - /** - * Called upon the creation of a new multiblock - * - * Handles the sign, registration - **/ - fun createNewMultiblock(multiblock: Multiblock, sign: Sign, detector: Player) = Tasks.sync { - detector.rewardAchievement(Achievement.DETECT_MULTIBLOCK) - - multiblock.setupSign(detector, sign) - - sign.persistentDataContainer.set( - NamespacedKeys.MULTIBLOCK, - PersistentDataType.STRING, - multiblock::class.simpleName!! // Shouldn't be any anonymous multiblocks - ) - - sign.isWaxed = true - sign.update() - } + private fun registerMultiblock(multiblock: Multiblock) {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt index a9a60a9974..4e35aa9c34 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt @@ -5,7 +5,6 @@ import com.google.common.cache.CacheLoader import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.debugHighlightBlock import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.old.Multiblocks import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -61,8 +60,7 @@ object Wires : IonServerComponent() { for ((x, y, z) in offsets) { val state = getStateIfLoaded(loc.world, loc.blockX + x, loc.blockY + y, loc.blockZ + z) val sign = state as? Sign ?: continue - val multiblock = Multiblocks[sign, true, false] as? PowerStoringMultiblock - ?: continue + val multiblock = null ?: continue return@from Optional.of(CachedPowerStore(multiblock, sign)) } return@from Optional.empty() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt index bc20d45cee..9c2cae1f9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt @@ -2,7 +2,8 @@ package net.horizonsend.ion.server.listener.misc import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.attribute.SmeltingResultAttribute -import net.horizonsend.ion.server.features.multiblock.Multiblocks +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded @@ -69,7 +70,7 @@ object FurnaceListener : SLEventListener() { } val sign = signBlock.getState(false) as Sign - val multiblock = Multiblocks[sign, false] + val multiblock: Multiblock? = null if (multiblock != null && !multiblock.name.contains("furnace")) { event.isCancelled = true From 9d8ff652089d770ba1cce5bfdc0ffcabdea57241 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 11 Oct 2024 03:30:07 -0500 Subject: [PATCH 229/500] migrate generator --- .../multiblock/MultiblockRegistration.kt | 7 + .../features/multiblock/old/Multiblocks.kt | 7 - .../power/generator/GeneratorMultiblock.kt | 142 +++++++++++++----- 3 files changed, 110 insertions(+), 46 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 0baa3f1856..6684fd95a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -53,6 +53,9 @@ import net.horizonsend.ion.server.features.multiblock.type.particleshield.Shield import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.charger.ChargerMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 @@ -166,6 +169,10 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(AutoCrafterMultiblockTier2) registerMultiblock(AutoCrafterMultiblockTier3) + registerMultiblock(GeneratorMultiblockTier1) + registerMultiblock(GeneratorMultiblockTier2) + registerMultiblock(GeneratorMultiblockTier3) + registerMultiblock(CarbonPrinterMultiblock) registerMultiblock(TechnicalPrinterMultiblock) registerMultiblock(GlassPrinterMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index bc145a67eb..e2100d5c9e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -15,9 +15,6 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMu import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 @@ -35,10 +32,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(AmmoLoaderMultiblock) // Furnace start - registerMultiblock(GeneratorMultiblockTier1) - registerMultiblock(GeneratorMultiblockTier2) - registerMultiblock(GeneratorMultiblockTier3) - registerMultiblock(PowerFurnaceMultiblockTier1) registerMultiblock(PowerFurnaceMultiblockTier2) registerMultiblock(PowerFurnaceMultiblockTier3) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 290f346154..2bf6c9cc83 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -1,52 +1,37 @@ package net.horizonsend.ion.server.features.multiblock.type.power.generator +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.machine.GeneratorFuel -import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN +import net.kyori.adventure.text.format.NamedTextColor.RED import org.bukkit.Effect import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent - -abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : - Multiblock(), - PowerStoringMultiblock, - FurnaceMultiblock { - abstract val speed: Double - - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isBurning = false - event.burnTime = 0 - val inventory = furnace.inventory - - val smelting = inventory.smelting - - if (smelting != null && smelting.type != Material.PRISMARINE_CRYSTALS) { - return - } - - if (PowerMachines.getPower(sign) < this.maxPower) { - val fuelItem = inventory.fuel ?: return - val fuel = GeneratorFuel.getFuel(fuelItem) ?: return - - event.isBurning = true - event.burnTime = (fuel.cooldown / speed).toInt() - furnace.cookTime = (-1000).toShort() - - PowerMachines.addPower(sign, fuel.power) - - return - } else { - furnace.world.playEffect(furnace.location.add(0.5, 0.5, 0.5), Effect.SMOKE, 4) - } - event.isCancelled = true - } +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.persistence.PersistentDataAdapterContext +abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock { override val name = "generator" + abstract val speed: Double override val signText = createSignText( line1 = "&2Power", @@ -70,4 +55,83 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M at(x = +0, y = +0, z = +1).redstoneBlock() at(x = +1, y = +0, z = +1).anyGlassPane() } + + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): GeneratorMultiblockEntity { + return GeneratorMultiblockEntity(data, manager, this, x, y, z, world, structureDirection) + } + + class GeneratorMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: GeneratorMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusMultiblock, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + private fun sleepWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } + + override fun tick() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return sleepWithStatus(text("No Furnace"), 250) + + if (powerStorage.getPower() >= powerStorage.capacity) { + world.playEffect(getOrigin().location.add(0.5, 0.5, 0.5), Effect.SMOKE, 4) + sleepWithStatus(text("Power Full", RED), 200) + return + } + + val fuelItem = furnaceInventory.fuel ?: return sleepWithStatus(text("No Fuel", RED), 100) + val fuel = GeneratorFuel.getFuel(fuelItem) ?: return sleepWithStatus(text("Invalid Fuel", RED), 100) + + val sleepTicks = (fuel.cooldown / multiblock.speed).toInt() + sleepWithStatus(text("Working", GREEN), sleepTicks) + + fuelItem.amount-- + + val furnace = furnaceInventory.holder + + furnace?.burnTime = sleepTicks.toShort() + furnace?.update() + + powerStorage.addPower(fuel.power) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } + } } From b22177536ff0a8996540d7be8217b94a4a337bb1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 11 Oct 2024 13:37:08 -0500 Subject: [PATCH 230/500] add simple powered multi entity class --- .../display/modular/display/StatusDisplay.kt | 12 ++-- .../server/features/machine/AreaShields.kt | 2 +- .../server/features/machine/DecomposeTask.kt | 4 +- .../multiblock/entity/MultiblockEntity.kt | 2 +- .../entity/type/LegacyMultiblockEntity.kt | 7 +++ .../entity/type/ProcessingMultiblockEntity.kt | 52 ----------------- ...ultiblock.kt => StatusMultiblockEntity.kt} | 2 +- .../type/fluids/BasicFluidStoringEntity.kt | 4 +- .../type/power/PoweredMultiblockEntity.kt | 4 +- .../power/SimplePoweredMultiblockEntity.kt | 45 +++++++++++++++ .../ticked/StatusTickedMultiblockEntity.kt | 12 ++++ .../type/autocrafter/AutoCrafterMultiblock.kt | 44 +++------------ .../defense/passive/areashield/AreaShield.kt | 45 +++++---------- .../multiblock/type/drills/DrillMultiblock.kt | 54 ++++++------------ .../farming/harvester/HarvesterMultiblock.kt | 51 ++++------------- .../type/farming/planter/PlanterMultiblock.kt | 51 ++++------------- .../type/fluid/ElectrolysisMultiblock.kt | 4 +- .../collector/PipedGasCollectorMultiblock.kt | 3 +- .../type/misc/DecomposerMultiblock.kt | 35 +++--------- .../type/misc/DisposalMultiblock.kt | 39 +++---------- .../multiblock/type/misc/MobDefender.kt | 4 +- .../type/power/charger/ChargerMultiblock.kt | 50 ++++------------- .../power/generator/GeneratorMultiblock.kt | 46 +++------------ .../type/power/storage/PowerBankMultiblock.kt | 48 ++++------------ .../type/power/storage/PowerCellMultiblock.kt | 48 ++++------------ .../type/printer/CarbonProcessorMultiblock.kt | 44 +++------------ .../type/printer/PrinterMultiblock.kt | 46 +++------------ .../mininglasers/MiningLaserMultiblock.kt | 56 +++++-------------- .../subsystem/misc/MiningLaserSubsystem.kt | 2 +- 29 files changed, 235 insertions(+), 581 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/{StatusMultiblock.kt => StatusMultiblockEntity.kt} (93%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/StatusTickedMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt index df2327b819..96b885119d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt @@ -1,14 +1,14 @@ package net.horizonsend.ion.server.features.client.display.modular.display -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.kyori.adventure.text.Component class StatusDisplay( - private val statusSupplier: StatusMultiblock.StatusManager, - offsetLeft: Double, - offsetUp: Double, - offsetBack: Double, - scale: Float, + private val statusSupplier: StatusMultiblockEntity.StatusManager, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + scale: Float, ) : Display(offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: Runnable = Runnable { display() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index 81c0b78bfb..60bbd1995a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -31,7 +31,7 @@ object AreaShields : IonServerComponent() { val shields = location.world.ion.multiblockManager[AreaShield.AreaShieldEntity::class] return shields.filter { - val radius = it.multiblock.radius + explosionSize + val radius = it.poweredMultiblock.radius + explosionSize val shieldLoc = it.location return@filter shieldLoc.world == location.world && shieldLoc.isInRange(location, radius) && !it.removed diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt index c4fa8b1917..c0343a241e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt @@ -24,7 +24,7 @@ class DecomposeTask( ) : BukkitRunnable() { private var totalBlocksBroken = 0 - private var currentBlock: Block = entity.regionOrigin + private var currentBlock: Block = entity.getOrigin() override fun run() { try { @@ -145,7 +145,7 @@ class DecomposeTask( } private fun getNextBlock(block: Block): Block? { - val origin = entity.regionOrigin + val origin = entity.getOrigin() val right = entity.structureDirection.rightFace // + 1 to get one block inside the frame diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 77471eb6bb..720dda1ece 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -34,7 +34,6 @@ import org.bukkit.persistence.PersistentDataAdapterContext **/ abstract class MultiblockEntity( var manager: MultiblockManager, - open val multiblock: Multiblock, var x: Int, var y: Int, @@ -43,6 +42,7 @@ abstract class MultiblockEntity( var structureDirection: BlockFace ): PDCSerializable { + abstract val multiblock: Multiblock private var lastRetrieved = System.currentTimeMillis() /** Gets the time since this value was last retrieved */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt index 5fd38bfaf4..80b0ce957e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/LegacyMultiblockEntity.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type +import net.horizonsend.ion.common.utils.text.orEmpty +import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.front @@ -20,4 +22,9 @@ interface LegacyMultiblockEntity { sign.front().line(2, Component.empty()) sign.update() } + + fun resetSign(sign: Sign, multiblock: Multiblock) { + multiblock.signText.withIndex().forEach { sign.front().line(it.index, it.value.orEmpty()) } + sign.update() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt deleted file mode 100644 index 0b7763358f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProcessingMultiblockEntity.kt +++ /dev/null @@ -1,52 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type - -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataType - -/** - * A multiblock that handles the processing of something - * - * @param requiredProgress The number of ticks to finish this process - * @param currentProgress The current progress of the process - **/ -abstract class ProcessingMultiblockEntity( - manager: MultiblockManager, - type: Multiblock, - x: Int, - y: Int, - z: Int, - world: World, - signOffset: BlockFace, - val requiredProgress: Int, - var currentProgress: Int = 0 -) : MultiblockEntity(manager, type, x, y, z, world, signOffset), SyncTickingMultiblockEntity { - //TODO - // -recipe system - - abstract fun canProcess(): Boolean - abstract fun finishProcessing() - abstract fun startProcessing() - abstract fun process() - - override fun tick() { - if (currentProgress >= requiredProgress) { - currentProgress = 0 - finishProcessing() - return - } - - currentProgress++ - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - store.addAdditionalData(NamespacedKeys.PROCESSING_PROGRESS, PersistentDataType.INTEGER, currentProgress) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblockEntity.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblockEntity.kt index 0acbe937cd..a5d4fbf352 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/StatusMultiblockEntity.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.empty -interface StatusMultiblock { +interface StatusMultiblockEntity { val statusManager: StatusManager fun setStatus(status: Component) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index b51c86af94..2e8fc0344a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -17,7 +17,7 @@ import org.bukkit.persistence.PersistentDataAdapterContext **/ abstract class BasicFluidStoringEntity( manager: MultiblockManager, - multiblock: Multiblock, + override val multiblock: Multiblock, data: PersistentMultiblockData, x: Int, y: Int, @@ -25,7 +25,7 @@ abstract class BasicFluidStoringEntity( world: World, structureDirection: BlockFace, storage: InternalStorage -) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { +) : MultiblockEntity(manager, x, y, z, world, structureDirection), FluidStoringEntity { @Suppress("LeakingThis") override val capacities: Array = arrayOf( loadStoredResource(data, "main", Component.text("Main Storage"), NamespacedKeys.MAIN_STORAGE, storage) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 56756e106e..7806ed064b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -6,11 +6,11 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { - val multiblock: NewPoweredMultiblock<*> + val poweredMultiblock: NewPoweredMultiblock<*> val powerStorage: PowerStorage fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { - return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) + return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), poweredMultiblock.maxPower) } fun savePowerData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt new file mode 100644 index 0000000000..205753d927 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt @@ -0,0 +1,45 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.power + +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataAdapterContext + +abstract class SimplePoweredMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: Multiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, +) : MultiblockEntity(manager, x, y, z, world, structureDirection), PoweredMultiblockEntity { + override val powerStorage: PowerStorage = this.loadStoredPower(data) + protected abstract val displayHandler: TextDisplayHandler + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/StatusTickedMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/StatusTickedMultiblockEntity.kt new file mode 100644 index 0000000000..66ffad4cc5 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/StatusTickedMultiblockEntity.kt @@ -0,0 +1,12 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.ticked + +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.kyori.adventure.text.Component + +/** Meant to be used with independently implemented ticked interface, just provides a util function */ +interface StatusTickedMultiblockEntity : TickedMultiblockEntityParent, StatusMultiblockEntity { + fun sleepWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 0075aba1fd..029cb6a32b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -4,24 +4,20 @@ import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.common.utils.text.orEmpty import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -133,28 +129,22 @@ abstract class AutoCrafterMultiblock( class AutoCrafterEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val multiblock: AutoCrafterMultiblock, + override val poweredMultiblock: AutoCrafterMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, StatusMultiblock, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity { override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) - override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - private fun getInput(): Inventory? = getInventory(-2, 0, 1) private fun getRecipeHolder(): Inventory? = getInventory(0, 0, 1) private fun getOutput(): Inventory? = getInventory(+2, 0, 1) @@ -177,7 +167,7 @@ abstract class AutoCrafterMultiblock( val powerUsage = grid.filterNotNull().distinct().count() * POWER_USAGE_PER_INGREDIENT - try { for (iteration in (1..multiblock.iterations)) { + try { for (iteration in (1..poweredMultiblock.iterations)) { if (power < powerUsage) return sleepWithStatus(text("Low Power", RED), 250) val removeSlots = mutableListOf() // can be multiple times per slot, so list, not set @@ -258,25 +248,9 @@ abstract class AutoCrafterMultiblock( } } - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) - multiblock.signText.withIndex().forEach { sign.front().line(it.index, it.value.orEmpty()) } + resetSign(sign, multiblock) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index 6103b2ed2c..ebe90a899e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -5,15 +5,12 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -25,7 +22,6 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataAdapterContext import java.util.concurrent.TimeUnit abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { @@ -90,46 +86,33 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< } class AreaShieldEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val multiblock: AreaShield, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) - - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val poweredMultiblock: AreaShield, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, signDirection), LegacyMultiblockEntity { + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() override fun onLoad() { world.ion.multiblockManager.register(this) - - displayHandler.update() + super.onLoad() } override fun handleRemoval() { world.ion.multiblockManager.deregister(this) - - displayHandler.remove() + super.handleRemoval() } override fun onUnload() { world.ion.multiblockManager.deregister(this) - - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) + super.onUnload() } override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 383e694ff3..1fcb0d3c60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -8,13 +8,11 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity.UserManager -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager @@ -22,7 +20,6 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.player.CombatTimer -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils @@ -122,19 +119,23 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } class DrillMultiblockEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val multiblock: DrillMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + data: PersistentMultiblockData, + manager: MultiblockManager, + override val poweredMultiblock: DrillMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { override val tickingManager: TickingManager = TickingManager(interval = 5) override val userManager: UserManager = UserManager(data, persistent = true) + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + override fun tick() { val player = userManager.getUserPlayer() ?: return disable() @@ -219,7 +220,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } private fun getBlocksToDestroy(): MutableList { - val toDestroy = getSquareRegion(4, 0, 0, multiblock.radius, 1) { + val toDestroy = getSquareRegion(4, 0, 0, poweredMultiblock.radius, 1) { it.type == Material.AIR || it.type == Material.BEDROCK } @@ -235,28 +236,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { userManager.saveUserData(store) - savePowerData(store) - } - - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) + super.storeAdditionalData(store, adapterContext) } override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 32e2f96c45..960ce83cc8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -5,19 +5,17 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -33,7 +31,6 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.Ageable -import org.bukkit.persistence.PersistentDataAdapterContext abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { override val name: String = "harvester" @@ -113,28 +110,22 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I class HarvesterEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val multiblock: HarvesterMultiblock, + override val poweredMultiblock: HarvesterMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { - override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), StatusTickedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() override val tickingManager: TickingManager = TickingManager(interval = 20) - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - override fun tick() { val inventory = getInventory(right = 0, up = 0, forward = 2) ?: return tickingManager.sleep(1000) var broken = 0 @@ -142,7 +133,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I val initialPower = powerStorage.getPower() if (initialPower == 0) return sleepWithStatus(text("No Power", RED), 500) - val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) + val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, poweredMultiblock.regionDepth) for (block in region) { val data = block.blockData @@ -160,7 +151,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I } } - if ((broken + 1) * multiblock.powerPerCrop > initialPower) { + if ((broken + 1) * poweredMultiblock.powerPerCrop > initialPower) { tickingManager.sleep(500) break } @@ -175,35 +166,15 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I break } - if (broken >= multiblock.tierNumber) break + if (broken >= poweredMultiblock.tierNumber) break } if (broken == 0) return sleepWithStatus(text("Sleeping", BLUE, ITALIC), 100) - powerStorage.removePower(broken * multiblock.powerPerCrop) + powerStorage.removePower(broken * poweredMultiblock.powerPerCrop) setStatus(text("Working", GREEN)) } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 07ec5eb643..fb70374933 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -5,19 +5,17 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE @@ -32,7 +30,6 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory -import org.bukkit.persistence.PersistentDataAdapterContext abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { override val name: String = "planter" @@ -104,28 +101,22 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int class PlanterEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val multiblock: PlanterMultiblock, + override val poweredMultiblock: PlanterMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblock { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), StatusTickedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { override val tickingManager: TickingManager = TickingManager(interval = 20) - override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - override fun tick() { var planted = 0 val initialPower = powerStorage.getPower() @@ -136,7 +127,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int val seedItem = inventory.fuel ?: return sleepWithStatus(text("No Seeds", RED), 500) val crop = Crop.findBySeed(seedItem.type) ?: return sleepWithStatus( text("Unknown Crop", RED), 1000) - val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) + val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, poweredMultiblock.regionDepth) for (block in region) { if (block.type != Material.AIR) continue @@ -144,7 +135,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int if (!crop.canBePlanted(block)) continue if (block.lightFromBlocks < 7 && block.lightFromSky < 7) continue - if ((planted + 1) * multiblock.powerPerCrop > initialPower) { + if ((planted + 1) * poweredMultiblock.powerPerCrop > initialPower) { tickingManager.sleep(500) break } @@ -154,35 +145,15 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int crop.plant(block) - if (planted >= multiblock.tierNumber) break + if (planted >= poweredMultiblock.tierNumber) break } if (planted == 0) return sleepWithStatus(text("Sleeping", BLUE, ITALIC), 100) - powerStorage.removePower(planted * multiblock.powerPerCrop) + powerStorage.removePower(planted * poweredMultiblock.powerPerCrop) setStatus(text("Working", GREEN)) } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 9008abc1e6..024d39953b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -213,14 +213,14 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock = arrayOf( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt index 9ca03bea63..2ad9763576 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt @@ -10,19 +10,16 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.machine.DecomposeTask import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity.UserManager -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.listener.misc.ProtectionListener.isRegionDenied import net.horizonsend.ion.server.miscellaneous.utils.CHISELED_TYPES import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded @@ -74,15 +71,13 @@ object DecomposerMultiblock : Multiblock(), NewPoweredMultiblock { @@ -100,10 +97,13 @@ object AbstractDisposalMultiblock : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock { protected abstract val tierMaterial: Material @@ -94,18 +90,16 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere } class ChargerEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val multiblock: ChargerMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) - - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val poweredMultiblock: ChargerMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, signDirection), LegacyMultiblockEntity { + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() @@ -144,7 +138,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere return } - var multiplier = powerPerSecond + var multiplier = poweredMultiblock.powerPerSecond multiplier /= item.amount if (item.amount * multiplier > power) return @@ -160,26 +154,6 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere event.burnTime = 20 } - override fun onLoad() { - displayHandler.update() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 2bf6c9cc83..4f33588c26 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -5,19 +5,16 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED @@ -27,7 +24,6 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory -import org.bukkit.persistence.PersistentDataAdapterContext abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock { override val name = "generator" @@ -63,28 +59,22 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M class GeneratorMultiblockEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val multiblock: GeneratorMultiblock, + override val poweredMultiblock: GeneratorMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusMultiblock, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity { override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) - override val statusManager: StatusMultiblock.StatusManager = StatusMultiblock.StatusManager() + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - override fun tick() { val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return sleepWithStatus(text("No Furnace"), 250) @@ -97,7 +87,7 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M val fuelItem = furnaceInventory.fuel ?: return sleepWithStatus(text("No Fuel", RED), 100) val fuel = GeneratorFuel.getFuel(fuelItem) ?: return sleepWithStatus(text("Invalid Fuel", RED), 100) - val sleepTicks = (fuel.cooldown / multiblock.speed).toInt() + val sleepTicks = (fuel.cooldown / poweredMultiblock.speed).toInt() sleepWithStatus(text("Working", GREEN), sleepTicks) fuelItem.amount-- @@ -110,26 +100,6 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M powerStorage.addPower(fuel.power) } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index fa0345e9be..b958c84a65 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -4,23 +4,19 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers.newMultiblockSignOverlay import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataAdapterContext abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { abstract val tierMaterial: Material @@ -112,42 +108,20 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM } class PowerBankEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val multiblock: PowerBankMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - structureDirection: BlockFace - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) - - private val displayHandler = newMultiblockSignOverlay( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val poweredMultiblock: PowerBankMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val displayHandler = newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 83cbb533d4..0cc58fe295 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -3,19 +3,15 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.persistence.PersistentDataAdapterContext object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "powercell" @@ -61,42 +57,20 @@ object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower: Int = 30000 @@ -98,23 +94,17 @@ object CarbonProcessorMultiblock : Multiblock(), NewPoweredMultiblock { override val name: String = "printer" @@ -137,28 +133,22 @@ abstract class PrinterMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "mininglaser" @@ -40,28 +36,22 @@ abstract class MiningLaserMultiblock : Multiblock(), NewPoweredMultiblock Date: Fri, 11 Oct 2024 14:26:43 -0500 Subject: [PATCH 231/500] add progress holder --- .../entity/type/ProgressMultiblock.kt | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt new file mode 100644 index 0000000000..1dfe1ce8ae --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -0,0 +1,48 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth +import net.horizonsend.ion.common.utils.text.colors.HEColorScheme +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.PROGRESS +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.TextColor +import org.bukkit.persistence.PersistentDataType.DOUBLE +import java.time.Duration + +interface ProgressMultiblock { + val progressManager: ProgressManager + + class ProgressManager(data: PersistentMultiblockData) { + private var currentProgress: Double = data.getAdditionalDataOrDefault(PROGRESS, DOUBLE, 0.0) + + /** + * Increments progress with a percentage of a total duration. + * Returns whether the progress has reached 100% + **/ + fun addProgress(totalDuration: Duration, delta: Duration): Boolean { + // Convert the delta to a percentage of the total duration, and add that percentage + val additionalPercent = totalDuration.toMillis().toDouble() / delta.toMillis().toDouble() + currentProgress += additionalPercent + + return isComplete() + } + + fun isComplete(): Boolean { + return currentProgress > 1.0 + } + + fun reset() { + currentProgress = 0.0 + } + + fun saveProgressData(store: PersistentMultiblockData) { + store.addAdditionalData(PROGRESS, DOUBLE, currentProgress) + } + + fun formatProgress(color: TextColor): Component { + return ofChildren(text(currentProgress.roundToHundredth() * 100.0, color), text('%', HEColorScheme.HE_LIGHT_GRAY)) + } + } +} From 0a1a0af5ef1eca2e186f3091d4a239a17c688c68 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 16 Oct 2024 14:09:34 -0500 Subject: [PATCH 232/500] persist progress over server restarts --- .../multiblock/entity/type/ProgressMultiblock.kt | 11 +++++++++++ .../registrations/persistence/NamespacedKeys.kt | 1 + 2 files changed, 12 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 1dfe1ce8ae..64fb7535a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -4,17 +4,27 @@ import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LAST_PROGRESS_TICK import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.PROGRESS import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.TextColor import org.bukkit.persistence.PersistentDataType.DOUBLE +import org.bukkit.persistence.PersistentDataType.LONG import java.time.Duration interface ProgressMultiblock { val progressManager: ProgressManager + fun tickProgress(totalDuration: Duration) { + val current = System.currentTimeMillis() + val delta = Duration.ofMillis(current - progressManager.lastProgressTick) + + progressManager.lastProgressTick = current + progressManager.addProgress(totalDuration, delta) + } class ProgressManager(data: PersistentMultiblockData) { + var lastProgressTick: Long = data.getAdditionalDataOrDefault(LAST_PROGRESS_TICK, LONG, System.currentTimeMillis()) private var currentProgress: Double = data.getAdditionalDataOrDefault(PROGRESS, DOUBLE, 0.0) /** @@ -39,6 +49,7 @@ interface ProgressMultiblock { fun saveProgressData(store: PersistentMultiblockData) { store.addAdditionalData(PROGRESS, DOUBLE, currentProgress) + store.addAdditionalData(LAST_PROGRESS_TICK, LONG, lastProgressTick) } fun formatProgress(color: TextColor): Component { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 27f05bd8d0..cb47ca6e71 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -67,6 +67,7 @@ object NamespacedKeys { val MATERIAL = key("material") val PROGRESS = key("progress") + val LAST_PROGRESS_TICK = key("last_progress_tick") val CUSTOM_ITEM_RESULT = key("custom_item_result") val ORE_POSITIONS = key("ore_positions") From 63bf38a55ef125c5c6b14f790b5cf153cd22bdbb Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 17 Oct 2024 00:14:58 -0500 Subject: [PATCH 233/500] new recipe system, needs testing --- .../multiblock/MultiblockRegistration.kt | 14 + .../multiblock/crafting/MultiblockRecipes.kt | 275 +++++++++--------- .../crafting/ingredient/Consumable.kt | 46 ++- .../ingredient/ConsumedItemIngredient.kt | 14 - .../crafting/ingredient/FluidIngredient.kt | 26 ++ .../ingredient/GasCanisterIngredient.kt | 20 -- .../crafting/ingredient/ItemConsumable.kt | 9 - .../crafting/ingredient/ItemIngredient.kt | 55 +++- .../ingredient/MultiblockRecipeIngredient.kt | 10 +- .../crafting/ingredient/PowerIngredient.kt | 23 ++ .../ProgressHolderItemIngredient.kt | 19 -- .../crafting/ingredient/ResourceIngredient.kt | 19 -- .../crafting/recipe/FurnaceEventHandler.kt | 9 - .../recipe/FurnaceMultiblockRecipe.kt | 69 ++--- .../crafting/recipe/MultiblockRecipe.kt | 20 +- .../recipe/ProcessingMultiblockRecipe.kt | 61 ++-- .../crafting/recipe/ProviderRecipe.kt | 33 +++ .../crafting/recipe/RecipeExecutionContext.kt | 25 ++ .../crafting/result/ActionResult.kt | 9 +- .../multiblock/crafting/result/ItemResult.kt | 54 ++-- .../crafting/result/MultiRecipeResult.kt | 25 +- .../crafting/result/MultiblockRecipeResult.kt | 12 +- .../crafting/result/ProgressItemResult.kt | 41 --- .../crafting/result/ProgressResult.kt | 27 ++ .../crafting/result/ResourceResult.kt | 15 - .../multiblock/crafting/result/SoundResult.kt | 13 +- .../entity/type/ProgressMultiblock.kt | 4 +- .../multiblock/entity/type/RecipeEntity.kt | 18 ++ .../features/multiblock/old/Multiblocks.kt | 12 - .../multiblock/type/FurnaceMultiblock.kt | 20 -- .../type/ammo/AmmoLoaderMultiblock.kt | 39 ++- .../type/ammo/MissileLoaderMultiblock.kt | 41 ++- .../type/industry/CentrifugeMultiblock.kt | 57 ++-- .../type/industry/CircuitfabMultiblock.kt | 43 ++- .../type/industry/CompressorMultiblock.kt | 43 ++- .../type/industry/FabricatorMultiblock.kt | 43 ++- .../type/industry/GasFurnaceMultiblock.kt | 50 ++-- .../type/industry/PlatePressMultiblock.kt | 39 ++- 38 files changed, 790 insertions(+), 562 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ResourceResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 6684fd95a9..35ebcd05fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -31,6 +31,12 @@ import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMul import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall +import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock @@ -180,6 +186,14 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(CarbonProcessorMultiblock) + // Crafting + registerMultiblock(CentrifugeMultiblock) + registerMultiblock(CompressorMultiblock) + registerMultiblock(FabricatorMultiblock) + registerMultiblock(CircuitfabMultiblock) + registerMultiblock(PlatePressMultiblock) + registerMultiblock(GasFurnaceMultiblock) + // Moreso powered multis than ship multis, could go in either spot tbh registerMultiblock(MiningLaserMultiblockTier1Top) registerMultiblock(MiningLaserMultiblockTier1Bottom) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt index a12709ed92..c5de880540 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt @@ -1,19 +1,19 @@ package net.horizonsend.ion.server.features.multiblock.crafting +import io.papermc.paper.util.Tick import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItems -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ConsumedItemIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.GasCanisterIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ProgressHolderItemIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.furnaceFuelIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.furnaceSmeltingIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceMultiblockRecipe import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import net.horizonsend.ion.server.features.multiblock.crafting.recipe.ProcessingMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult.Companion.furnaceRecipeResult import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiRecipeResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressResult import net.horizonsend.ion.server.features.multiblock.crafting.result.SoundResult +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock @@ -22,148 +22,157 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMu import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Material import org.bukkit.SoundCategory -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import java.util.LinkedList import java.util.concurrent.ConcurrentHashMap +import kotlin.reflect.KClass @Suppress("UNUSED") object MultiblockRecipes : IonServerComponent() { - private val recipes: ConcurrentHashMap>> = ConcurrentHashMap() - - val URANIUM_ENRICHMENT = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = CentrifugeMultiblock, - smelting = ConsumedItemIngredient(CustomItems.URANIUM, 1), - result = MultiRecipeResult( - ItemResult(CustomItems.ENRICHED_URANIUM), - SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - resources = listOf(power(100)), + private val recipes: ConcurrentHashMap, LinkedList>> = ConcurrentHashMap() + + val URANIUM_ENRICHMENT = registerRecipe(ProcessingMultiblockRecipe( + multiblock = CentrifugeMultiblock, + multiblockEntityClass = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.URANIUM, 1), + result = MultiRecipeResult( + furnaceRecipeResult(CustomItems.ENRICHED_URANIUM), + SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + resources = listOf(PowerIngredient(100)), + )) + + val URANIUM_CORE_COMPRESSION = registerRecipe(ProcessingMultiblockRecipe( + multiblock = CompressorMultiblock, + multiblockEntityClass = CompressorMultiblock.CompressorMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.URANIUM_CORE, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.URANIUM_ROD)), + SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f) ) - ) - - val URANIUM_CORE_COMPRESSION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = CompressorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.URANIUM_CORE, 1), progressHolderResult = CustomItems.URANIUM_ROD), - resources = listOf(power(100)), - result = MultiRecipeResult( - ProgressItemResult(CustomItems.URANIUM_ROD, 60L * 60L * 20L, SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) + )) + + val STEEL_PRODUCTION = registerRecipe(FurnaceMultiblockRecipe( + multiblock = GasFurnaceMultiblock, + multiblockEntityClass = GasFurnaceMultiblock.GasFurnaceMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(ItemStack(Material.IRON_INGOT), 1), + fuel = furnaceFuelIngredient(CustomItems.GAS_CANISTER_OXYGEN, 5), + resources = listOf(PowerIngredient(100)), + result = furnaceRecipeResult(CustomItems.STEEL_INGOT) + )) + + val REACTIVE_PLATING_PRESSING = registerRecipe(ProcessingMultiblockRecipe( + multiblock = PlatePressMultiblock, + multiblockEntityClass = PlatePressMultiblock.PlatePressMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.REACTIVE_PLATING, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.REACTIVE_CHASSIS)), + SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f) ) - ) - - val STEEL_PRODUCTION = registerRecipe( - FurnaceMultiblockRecipe( - multiblock = GasFurnaceMultiblock, - smelting = ConsumedItemIngredient(ItemStack(Material.IRON_INGOT), 1), - fuel = GasCanisterIngredient(CustomItems.GAS_CANISTER_OXYGEN, 5), - resources = listOf(power(100)), - result = ItemResult(CustomItems.STEEL_INGOT) + )) + + val STEEL_PLATE_PRESSING = registerRecipe(ProcessingMultiblockRecipe( + multiblock = PlatePressMultiblock, + multiblockEntityClass = PlatePressMultiblock.PlatePressMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.STEEL_PLATE, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.STEEL_CHASSIS)), + SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f) ) - ) - - val REACTIVE_PLATING_PRESSING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = PlatePressMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.REACTIVE_PLATING, 1), progressHolderResult = CustomItems.REACTIVE_CHASSIS), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.REACTIVE_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val STEEL_PLATE_PRESSING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = PlatePressMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.STEEL_PLATE, 1), progressHolderResult = CustomItems.STEEL_CHASSIS), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.STEEL_CHASSIS, 60L * 60L * 20L, SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val FUEL_ROD_CORE_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.FUEL_ROD_CORE, 1), progressHolderResult = CustomItems.FUEL_CELL), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.FUEL_CELL, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val FABRICATED_ASSEMBLY_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.REACTIVE_ASSEMBLY, 1), progressHolderResult = CustomItems.FABRICATED_ASSEMBLY), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.FABRICATED_ASSEMBLY, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val REINFORCED_FRAME_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.STEEL_ASSEMBLY, 1), progressHolderResult = CustomItems.REINFORCED_FRAME), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.REINFORCED_FRAME, 60L * 60L * 20L * 2L, SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val CIRCUIT_BOARD_FABRICATION = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = CircuitfabMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.CIRCUITRY, 1), progressHolderResult = CustomItems.CIRCUIT_BOARD), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.CIRCUIT_BOARD, 60L * 60L * 20L, SoundResult("horizonsend:industry.cirfab", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val LOADED_SHELL_LOADING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = AmmoLoaderMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNLOADED_SHELL, 1), progressHolderResult = CustomItems.LOADED_SHELL), - resources = listOf(power(100)), - result = MultiRecipeResult(ProgressItemResult(CustomItems.LOADED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f))) - ) - ) - - val UNCHARGED_SHELL_CHARGING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = AmmoLoaderMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNCHARGED_SHELL, 1), progressHolderResult = CustomItems.CHARGED_SHELL), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.CHARGED_SHELL, 90L * 20L, SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - val ARSENAL_MISSILE_LOADING = registerRecipe( - ProcessingMultiblockRecipe( - multiblock = MissileLoaderMultiblock, - smelting = ProgressHolderItemIngredient(initialIngredient = ConsumedItemIngredient(CustomItems.UNLOADED_ARSENAL_MISSILE, 1), progressHolderResult = CustomItems.ARSENAL_MISSILE), - resources = listOf(power(100)), - result = ProgressItemResult(CustomItems.ARSENAL_MISSILE, 60L * 60L * 20L, SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f)) - ) - ) - - /** - * Add a power ingredient - **/ - private fun power(amount: Int) = ResourceIngredient(NamespacedKeys.POWER, amount) - - private fun registerRecipe(recipe: MultiblockRecipe): MultiblockRecipe { - recipes.getOrPut(recipe.multiblock) { LinkedList() }.add(recipe) + )) + + val FUEL_ROD_CORE_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( + multiblock = FabricatorMultiblock, + multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.FUEL_ROD_CORE, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItems.FUEL_CELL)), + SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + val FABRICATED_ASSEMBLY_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( + multiblock = FabricatorMultiblock, + multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.REACTIVE_ASSEMBLY, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItems.FABRICATED_ASSEMBLY)), + SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + val REINFORCED_FRAME_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( + multiblock = FabricatorMultiblock, + multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.STEEL_ASSEMBLY, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItems.REINFORCED_FRAME)), + SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + val CIRCUIT_BOARD_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( + multiblock = CircuitfabMultiblock, + multiblockEntityClass = CircuitfabMultiblock.CircuitfabMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.CIRCUITRY, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.CIRCUIT_BOARD)), + SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + val LOADED_SHELL_LOADING = registerRecipe(ProcessingMultiblockRecipe( + multiblock = AmmoLoaderMultiblock, + multiblockEntityClass = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.UNLOADED_SHELL, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItems.LOADED_SHELL)), + SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + val UNCHARGED_SHELL_CHARGING = registerRecipe(ProcessingMultiblockRecipe( + multiblock = AmmoLoaderMultiblock, + multiblockEntityClass = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.UNCHARGED_SHELL, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItems.CHARGED_SHELL)), + SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + val ARSENAL_MISSILE_LOADING = registerRecipe(ProcessingMultiblockRecipe( + multiblock = MissileLoaderMultiblock, + multiblockEntityClass = MissileLoaderMultiblock.MissileLoaderMultiblockEntity::class, + smelting = furnaceSmeltingIngredient(CustomItems.UNLOADED_ARSENAL_MISSILE, 1), + resources = listOf(PowerIngredient(100)), + result = MultiRecipeResult( + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.ARSENAL_MISSILE)), + SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f) + ), + )) + + private fun registerRecipe(recipe: MultiblockRecipe): MultiblockRecipe { + recipes.getOrPut(recipe.entityClass) { LinkedList() }.add(recipe) return recipe } - fun getRecipe(multiblock: T, sign: Sign, inventory: Inventory): MultiblockRecipe? { + fun getRecipe(entity: T): MultiblockRecipe? { @Suppress("UNCHECKED_CAST") - val recipesFor = (recipes[multiblock] as? LinkedList>) ?: return null + val recipesFor = (recipes[entity::class] as? LinkedList>) ?: return null - return recipesFor.firstOrNull { it.matches(sign, inventory) } + return recipesFor.shuffled().firstOrNull { it.canExecute(entity) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt index 258fbb35a5..8b8b7673ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt @@ -1,8 +1,46 @@ package net.horizonsend.ion.server.features.multiblock.crafting.ingredient -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign +import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.custom.items.GasCanister +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import org.bukkit.inventory.ItemStack -interface Consumable { - fun consume(multiblock: Multiblock, sign: Sign) +interface Consumable { + fun checkRequirement(item: ItemStack?, context: RecipeExecutionContext): Boolean + + fun consumeIngredient(item: ItemStack, context: RecipeExecutionContext): Boolean + + class ItemConsumable(val itemStack: ItemStack, val amount: Int) : Consumable { + override fun checkRequirement(item: ItemStack?, context: RecipeExecutionContext): Boolean { + if (item == null) return false + if (!itemStack.isSimilar(item)) return false + + return item.amount >= amount + } + + override fun consumeIngredient(item: ItemStack, context: RecipeExecutionContext): Boolean { + item.amount -= amount + return true + } + } + + class GasCanisterConsumable(private val canister: GasCanister, val amount: Int) : Consumable { + override fun checkRequirement(item: ItemStack?, context: RecipeExecutionContext): Boolean { + if (item == null) return false + + val customItem = item.customItem + + if (customItem !is GasCanister) return false + if (customItem.gas != canister.gas) return false + + return canister.getFill(item) > amount + } + + override fun consumeIngredient(item: ItemStack, context: RecipeExecutionContext): Boolean { + val oldFill = canister.getFill(item) + canister.setFill(item, oldFill - amount) + return true + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt deleted file mode 100644 index 3bd6420e9e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ConsumedItemIngredient.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack - -class ConsumedItemIngredient(ingredient: ItemStack, amount: Int) : ItemIngredient(ingredient, amount), ItemConsumable { - constructor(ingredient: CustomItem, amount: Int) : this(ingredient.constructItemStack(), amount) - - override fun consume(multiblock: Multiblock, sign: Sign, itemStack: ItemStack) { - itemStack.amount -= amount - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt new file mode 100644 index 0000000000..a0e9078367 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +class FluidIngredient(val fluid: PipedFluid, val amount: Int) : MultiblockRecipeIngredient { + override fun checkRequirement(context: RecipeExecutionContext): Boolean { + val entity = context.entity + + if (entity !is FluidStoringEntity) return false + + return entity.capacities.any { it.internalStorage.getStoredFluid() == fluid && it.internalStorage.getAmount() >= amount } + } + + override fun consumeIngredient(context: RecipeExecutionContext): Boolean { + val entity = context.entity + + if (entity !is FluidStoringEntity) return false + + return (entity.capacities.firstOrNull { + it.internalStorage.getStoredFluid() == fluid && it.internalStorage.getAmount() >= amount + }?.internalStorage?.remove(amount) ?: amount) == 0 + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt deleted file mode 100644 index b07f582741..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/GasCanisterIngredient.kt +++ /dev/null @@ -1,20 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.type.GasCanister -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack - -class GasCanisterIngredient(private val canister: GasCanister, val amount: Int) : MultiblockRecipeIngredient, ItemConsumable { - override fun checkRequirement(multiblock: Multiblock, sign: Sign, itemStack: ItemStack?): Boolean { - if (itemStack == null) return false - if (itemStack.customItem != canister) return false - - return canister.getFill(itemStack) >= amount - } - - override fun consume(multiblock: Multiblock, sign: Sign, itemStack: ItemStack) { - canister.setFill(itemStack, canister.getFill(itemStack) - amount) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt deleted file mode 100644 index ee28313fa8..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemConsumable.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack - -interface ItemConsumable { - fun consume(multiblock: Multiblock, sign: Sign, itemStack: ItemStack) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt index beadd9455b..a987691563 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt @@ -1,15 +1,56 @@ package net.horizonsend.ion.server.features.multiblock.crafting.ingredient -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.GasCanister +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack -open class ItemIngredient(val ingredient: ItemStack, val amount: Int) : MultiblockRecipeIngredient { +class ItemIngredient( + private val itemConsumable: Consumable, + private val cast: RecipeExecutionContext.() -> B?, + private val acquireItem: (B) -> ItemStack? +) : MultiblockRecipeIngredient { + override fun checkRequirement(context: RecipeExecutionContext): Boolean { + val acquiredItem = getItem(context) ?: return false + return itemConsumable.checkRequirement(acquiredItem, context) + } + + override fun consumeIngredient(context: RecipeExecutionContext): Boolean { + val acquiredItem = getItem(context) ?: return false + return itemConsumable.consumeIngredient(acquiredItem, context) + } + + fun getItem(context: RecipeExecutionContext): ItemStack? { + val inventory = cast.invoke(context) ?: return null + return acquireItem.invoke(inventory) + } + + companion object { + const val MAIN_FURNACE_STRING = "mainFurnace" + + fun furnaceFuelConsumable(consumable: Consumable) = ItemIngredient( + consumable, + { getLabeledInventory(MAIN_FURNACE_STRING) as? FurnaceInventory }, + { it.fuel } + ) + + fun furnaceFuelIngredient(item: ItemStack, amount: Int) = furnaceFuelConsumable(Consumable.ItemConsumable(item, amount)) + fun furnaceFuelIngredient(canister: GasCanister, amount: Int) = furnaceFuelConsumable(Consumable.GasCanisterConsumable(canister, amount)) + fun furnaceFuelIngredient(item: CustomItem, amount: Int) = furnaceFuelIngredient(item.constructItemStack(), amount) - override fun checkRequirement(multiblock: Multiblock, sign: Sign, itemStack: ItemStack?): Boolean { - if (itemStack == null) return false - if (!itemStack.isSimilar(ingredient)) return false + fun furnaceSmeltingIngredient(item: ItemStack, amount: Int) = ItemIngredient( + Consumable.ItemConsumable(item, amount), + { getLabeledInventory(MAIN_FURNACE_STRING) as? FurnaceInventory }, + { it.smelting } + ) - return itemStack.amount >= amount + fun furnaceSmeltingIngredient(item: CustomItem, amount: Int) = ItemIngredient( + Consumable.ItemConsumable(item.constructItemStack(), amount), + { getLabeledInventory(MAIN_FURNACE_STRING) as? FurnaceInventory }, + { it.smelting } + ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt index d8d697df66..88bda4a523 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.crafting.ingredient -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -interface MultiblockRecipeIngredient { - fun checkRequirement(multiblock: Multiblock, sign: Sign, itemStack: ItemStack?): Boolean +interface MultiblockRecipeIngredient { + fun checkRequirement(context: RecipeExecutionContext): Boolean + fun consumeIngredient(context: RecipeExecutionContext): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt new file mode 100644 index 0000000000..a4aeb67208 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt @@ -0,0 +1,23 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.ingredient + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity + +class PowerIngredient(val amount: Int) : MultiblockRecipeIngredient { + override fun checkRequirement(context: RecipeExecutionContext): Boolean { + val entity = context.entity + + if (entity !is PoweredMultiblockEntity) return false + + return entity.powerStorage.getPower() >= amount + } + + override fun consumeIngredient(context: RecipeExecutionContext): Boolean { + val entity = context.entity + + if (entity !is PoweredMultiblockEntity) return false + + return entity.powerStorage.removePower(amount) == 0 + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt deleted file mode 100644 index 2c285c2c17..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ProgressHolderItemIngredient.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.type.ProgressHolder -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack - -class ProgressHolderItemIngredient(val initialIngredient: ItemIngredient, val progressHolderResult: CustomItem) : MultiblockRecipeIngredient { - override fun checkRequirement(multiblock: Multiblock, sign: Sign, itemStack: ItemStack?): Boolean { - if (initialIngredient.checkRequirement(multiblock, sign, itemStack)) return true - - if (itemStack == null) return false - if (itemStack.customItem !is ProgressHolder) return false - - return ProgressHolder.getResult(itemStack) == progressHolderResult - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt deleted file mode 100644 index 9739c92fc2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ResourceIngredient.kt +++ /dev/null @@ -1,19 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.machine.PowerMachines.getPower -import net.horizonsend.ion.server.features.machine.PowerMachines.removePower -import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.NamespacedKey -import org.bukkit.block.Sign -import org.bukkit.inventory.ItemStack - -class ResourceIngredient(val namespace: NamespacedKey, val amount: Int) : MultiblockRecipeIngredient, Consumable { - override fun checkRequirement(multiblock: Multiblock, sign: Sign, itemStack: ItemStack?): Boolean { - //TODO expand with gasses during multiblock update - return getPower(sign, true) >= amount - } - - override fun consume(multiblock: Multiblock, sign: Sign) { - removePower(sign, amount) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt deleted file mode 100644 index 7700835a88..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceEventHandler.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe - -import org.bukkit.block.Furnace -import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent - -interface FurnaceEventHandler { - fun handleFurnaceEvent(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt index 8073a5ad0b..bbdb887b8c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt @@ -1,62 +1,45 @@ package net.horizonsend.ion.server.features.multiblock.crafting.recipe -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemConsumable +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import org.bukkit.block.Sign -import org.bukkit.block.data.type.Furnace -import org.bukkit.event.inventory.FurnaceBurnEvent +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.Inventory +import kotlin.reflect.KClass /** * Recipes that use both slots of a furnace * * Do NOT try to use this on a non-furnace inventory **/ -class FurnaceMultiblockRecipe( - override val multiblock: T, - val smelting: MultiblockRecipeIngredient, - val fuel: MultiblockRecipeIngredient, - private val resources: List = listOf(), - override val result: MultiblockRecipeResult -) : MultiblockRecipe, FurnaceEventHandler { - override fun matches(sign: Sign, inventory: Inventory): Boolean { - inventory as FurnaceInventory - - if (resources.any { !it.checkRequirement(multiblock, sign, null) }) return false - if (!smelting.checkRequirement(multiblock, sign, inventory.smelting)) return false - - return fuel.checkRequirement(multiblock, sign, inventory.fuel) +class FurnaceMultiblockRecipe( + multiblock: EntityMultiblock, + multiblockEntityClass: KClass, + val smelting: MultiblockRecipeIngredient, + val fuel: MultiblockRecipeIngredient, + private val resources: List> = listOf(), + override val result: MultiblockRecipeResult +) : MultiblockRecipe(multiblock, multiblockEntityClass) { + override fun finalize(context: RecipeExecutionContext) { + result.execute(context) } - override fun execute(sign: Sign, inventory: Inventory) { - inventory as FurnaceInventory - - val holder = inventory.holder!! - if (!(holder.blockData as Furnace).isLit) return - - if (!result.canFit(this, inventory, sign)) return - - // Return if enough ingredients are not present - if (!smelting.checkRequirement(multiblock, sign, inventory.smelting)) return - if (!fuel.checkRequirement(multiblock, sign, inventory.fuel)) return - - if (resources.any { !it.checkRequirement(multiblock, sign, null) }) return - - result.execute(this, inventory, sign) - - if (smelting is ItemConsumable) smelting.consume(multiblock, sign, inventory.smelting!!) - if (fuel is ItemConsumable) fuel.consume(multiblock, sign, inventory.fuel!!) + override fun getLabeledInventories(context: RecipeExecutionContext): Map { + return mapOf(ItemIngredient.MAIN_FURNACE_STRING to context.entity.getInventory(0, 0, 0) as FurnaceInventory) + } - resources.forEach { it.consume(multiblock, sign) } + override fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean { + return smelting.checkRequirement(context) + && fuel.checkRequirement(context) + && resources.all { it.checkRequirement(context) } } - override fun handleFurnaceEvent(event: FurnaceBurnEvent, furnace: org.bukkit.block.Furnace, sign: Sign) { - event.isBurning = false - event.burnTime = 200 - event.isCancelled = false + override fun consumeResources(context: RecipeExecutionContext): Boolean { + return smelting.consumeIngredient(context) + && fuel.consumeIngredient(context) + && resources.all { it.consumeIngredient(context) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt index 8965039182..4ede119dc7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt @@ -1,15 +1,21 @@ package net.horizonsend.ion.server.features.multiblock.crafting.recipe -import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import org.bukkit.block.Sign +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.inventory.Inventory +import kotlin.reflect.KClass -interface MultiblockRecipe { - val multiblock: T - val result: MultiblockRecipeResult +abstract class MultiblockRecipe(val multiblock: EntityMultiblock, val entityClass: KClass) { + abstract val result: MultiblockRecipeResult - fun matches(sign: Sign, inventory: Inventory): Boolean + abstract fun finalize(context: RecipeExecutionContext) - fun execute(sign: Sign, inventory: Inventory) // TODO redesign this on multiblock rewrite branch + abstract fun getLabeledInventories(context: RecipeExecutionContext): Map + + abstract fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean + + abstract fun consumeResources(context: RecipeExecutionContext): Boolean + + fun canExecute(entity: T): Boolean = checkResourcesAvailable(RecipeExecutionContext(this, entity)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt index 651166223d..abe1f9228c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt @@ -1,63 +1,42 @@ package net.horizonsend.ion.server.features.multiblock.crafting.recipe -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemConsumable +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import org.bukkit.block.Furnace -import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.Inventory +import kotlin.reflect.KClass /** * A multiblock recipe that takes one ingredient, and produces one result * Usually furnace multiblocks with prismarine crystals occupying the bottom slot * - * @param time, in ticks * @param smelting, the input resource * @param result, the result of the recipe **/ -class ProcessingMultiblockRecipe( - override val multiblock: T, - val smelting: MultiblockRecipeIngredient, - override val result: MultiblockRecipeResult, - private val resources: List = listOf(), -) : MultiblockRecipe, FurnaceEventHandler { - init { - require(multiblock is FurnaceMultiblock) +class ProcessingMultiblockRecipe( + multiblock: EntityMultiblock, + multiblockEntityClass: KClass, + val smelting: MultiblockRecipeIngredient, + override val result: MultiblockRecipeResult, + private val resources: List> = listOf(), +) : MultiblockRecipe(multiblock, multiblockEntityClass) { + override fun finalize(context: RecipeExecutionContext) { + result.execute(context) } - override fun matches(sign: Sign, inventory: Inventory): Boolean { - inventory as FurnaceInventory - return smelting.checkRequirement(multiblock, sign, inventory.smelting) + override fun getLabeledInventories(context: RecipeExecutionContext): Map { + return mapOf(ItemIngredient.MAIN_FURNACE_STRING to context.entity.getInventory(0, 0, 0) as FurnaceInventory) } - override fun execute(sign: Sign, inventory: Inventory) { - inventory as FurnaceInventory - - val holder = inventory.holder!! - if (!(holder.blockData as org.bukkit.block.data.type.Furnace).isLit) return - - if (!result.canFit(this, inventory, sign)) return - - // Return if enough ingredients are not present - if (!smelting.checkRequirement(multiblock, sign, inventory.smelting)) return - - if (resources.any { !it.checkRequirement(multiblock, sign, null) }) return - - result.execute(this, inventory, sign) - - if (smelting is ItemConsumable) smelting.consume(multiblock, sign, inventory.smelting!!) - - resources.forEach { it.consume(multiblock, sign) } + override fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean { + return smelting.checkRequirement(context) && resources.all { it.checkRequirement(context) } } - override fun handleFurnaceEvent(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isBurning = false - event.burnTime = 200 - event.isCancelled = false + override fun consumeResources(context: RecipeExecutionContext): Boolean { + return smelting.consumeIngredient(context) && resources.all { it.consumeIngredient(context) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt new file mode 100644 index 0000000000..1763018b10 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt @@ -0,0 +1,33 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe + +import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import org.bukkit.inventory.Inventory +import kotlin.reflect.KClass + +class ProviderRecipe( + multiblock: EntityMultiblock, + entityClass: KClass, + override val result: MultiblockRecipeResult, + private val getLabeledInventories: RecipeExecutionContext.() -> Map, + private val checkResourcesAvailable: RecipeExecutionContext.() -> Boolean, + private val consumeResources: RecipeExecutionContext.() -> Boolean +) : MultiblockRecipe(multiblock, entityClass) { + + override fun consumeResources(context: RecipeExecutionContext): Boolean { + return consumeResources.invoke(context) + } + + override fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean { + return checkResourcesAvailable.invoke(context) + } + + override fun getLabeledInventories(context: RecipeExecutionContext): Map { + return getLabeledInventories.invoke(context) + } + + override fun finalize(context: RecipeExecutionContext) { + result.execute(context) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt new file mode 100644 index 0000000000..eb73806d4f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt @@ -0,0 +1,25 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import org.bukkit.inventory.Inventory + +class RecipeExecutionContext(val recipe: MultiblockRecipe, val entity: T) { + private var aborted: Boolean = false + private lateinit var inventories: Map + + fun getLabeledInventory(name: String): Inventory = inventories[name]!! + + fun execute() { + inventories = recipe.getLabeledInventories(this) + if (aborted) return + if (!recipe.checkResourcesAvailable(this)) return + if (aborted) return + if (!recipe.consumeResources(this)) return + if (aborted) return + recipe.finalize(this) + } + + fun abort() { + aborted = true + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt index 715fe2ceb7..524dded711 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt @@ -1,11 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -fun interface ActionResult : MultiblockRecipeResult { - override fun canFit(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign): Boolean { +fun interface ActionResult : MultiblockRecipeResult { + override fun canFit(context: RecipeExecutionContext): Boolean { return true } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt index a5b2cad451..5b3cbfc3e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt @@ -1,31 +1,51 @@ package net.horizonsend.ion.server.features.multiblock.crafting.result import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import org.bukkit.block.Sign -import org.bukkit.inventory.CraftingInventory +import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.MAIN_FURNACE_STRING +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack -import java.util.function.Supplier -open class ItemResult(val result: ItemStack, private val count: Int = 1) : MultiblockRecipeResult { - constructor(item: CustomItem, count: Int = 1) : this(item.constructItemStack(), count) +open class ItemResult( + private val result: ItemStack, + private val count: Int, + val outputInventory: String, + val check: (Inventory, ItemStack) -> Boolean, + val add: (Inventory, ItemStack) -> Unit, +) : MultiblockRecipeResult { - override fun canFit(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign): Boolean { - if (((craftingInventory as? CraftingInventory)?.result?.amount ?: 0) >= result.maxStackSize) return false - if (((craftingInventory as? FurnaceInventory)?.result?.amount ?: 0) >= result.maxStackSize) return false - return true + override fun canFit(context: RecipeExecutionContext): Boolean { + val inv = context.getLabeledInventory(outputInventory) + return check.invoke(inv, result.asQuantity(count)) } - override fun execute(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) { - applyResultTo(craftingInventory) { result.asQuantity(count) } + override fun execute(context: RecipeExecutionContext) { + val inv = context.getLabeledInventory(outputInventory) + add.invoke(inv, result.asQuantity(count)) } - private fun applyResultTo(inventory: Inventory, result: Supplier) { - when (inventory) { - is CraftingInventory -> inventory.result?.add(1) ?: run { inventory.result = result.get() } - is FurnaceInventory -> inventory.result?.add(1) ?: run { inventory.result = result.get() } - } + companion object { + fun furnaceRecipeResult(resultItem: ItemStack, quantity: Int = 1) = ItemResult( + resultItem, + quantity, + MAIN_FURNACE_STRING, + check@ { inv, item -> + val resultSLot = (inv as FurnaceInventory).result ?: return@check true + if (!resultSLot.isSimilar(item)) return@check true + resultSLot.amount + quantity < resultItem.maxStackSize + }, + add@ { inv, item -> + val resultSLot = (inv as FurnaceInventory).result + if (resultSLot?.isSimilar(item) == true) { + resultSLot.amount += quantity + } + + if (resultSLot == null) inv.result = item + } + ) + + fun furnaceRecipeResult(resultItem: CustomItem, quantity: Int = 1) = furnaceRecipeResult(resultItem.constructItemStack(), quantity) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt index 46241f3860..bb25f25eb1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt @@ -1,24 +1,23 @@ package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity /** * Wrap multiple result actions **/ -class MultiRecipeResult( - val main: MultiblockRecipeResult, - vararg others: ActionResult -) : MultiblockRecipeResult { - val actions = others.toList() +class MultiRecipeResult( + val main: MultiblockRecipeResult, + vararg others: ActionResult +) : MultiblockRecipeResult { + private val actions = others.toList() - override fun canFit(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign): Boolean { - return main.canFit(recipe, craftingInventory, sign) + override fun canFit(context: RecipeExecutionContext): Boolean { + return main.canFit(context) } - override fun execute(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) { - main.execute(recipe, craftingInventory, sign) - actions.forEach { it.execute(recipe, craftingInventory, sign) } + override fun execute(context: RecipeExecutionContext) { + main.execute(context) + actions.forEach { it.execute(context) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt index ce5d9ed5ab..49410bfb1b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt @@ -1,11 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -interface MultiblockRecipeResult { - fun canFit(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign): Boolean - - fun execute(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) +interface MultiblockRecipeResult { + fun canFit(context: RecipeExecutionContext): Boolean + fun execute(context: RecipeExecutionContext) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt deleted file mode 100644 index da39407f7c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressItemResult.kt +++ /dev/null @@ -1,41 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.type.ProgressHolder -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import org.bukkit.block.Sign -import org.bukkit.inventory.FurnaceInventory -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.ItemStack - -/** - * This item will convert into the result custom item after the amount of ticks provided (Assuming no lag and a 200 tick interval on the furnace) - **/ -class ProgressItemResult(val result: R, time: Long, private val onComplete: ActionResult? = null) : ActionResult { - // 200 is the standard furnace tick interval - private val increment = 200.0 / time.toDouble() - - override fun execute(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) { - if (craftingInventory !is FurnaceInventory) return - - val smelting = craftingInventory.smelting ?: return - - if (smelting.customItem is ProgressHolder) { - incrementProgress(smelting, craftingInventory, recipe, craftingInventory, sign) - return - } - - craftingInventory.smelting = ProgressHolder.create(result) - } - - private fun incrementProgress(progressItem: ItemStack, inventory: FurnaceInventory, recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) { - val current = ProgressHolder.getProgress(progressItem) - - if (ProgressHolder.setProgress(progressItem, current + increment)) { - inventory.result = inventory.smelting - inventory.smelting = null - onComplete?.execute(recipe, craftingInventory, sign) ?: return - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt new file mode 100644 index 0000000000..a0be7a637f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt @@ -0,0 +1,27 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.result + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import java.time.Duration + +/** + * This item will convert into the result custom item after the amount of ticks provided (Assuming no lag and a 200 tick interval on the furnace) + **/ +class ProgressResult( + val duration: Duration, + val finalResult: MultiblockRecipeResult +) : MultiblockRecipeResult { + override fun canFit(context: RecipeExecutionContext): Boolean { + return finalResult.canFit(context) + } + + override fun execute(context: RecipeExecutionContext) { + val multiblock = context.entity as ProgressMultiblock + + if (multiblock.tickProgress(duration)) { + multiblock.progressManager.reset() + finalResult.execute(context) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ResourceResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ResourceResult.kt deleted file mode 100644 index 9b1f9cd82e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ResourceResult.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory - -class ResourceResult : MultiblockRecipeResult { - override fun canFit(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign): Boolean { - TODO("Not yet implemented") - } - - override fun execute(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) { - TODO("Not yet implemented") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt index d505724620..0a7912e309 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt @@ -1,19 +1,18 @@ package net.horizonsend.ion.server.features.multiblock.crafting.result -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import org.bukkit.Registry import org.bukkit.Sound import org.bukkit.SoundCategory -import org.bukkit.block.Sign -import org.bukkit.inventory.Inventory -class SoundResult(val sound: String, private val soundCategory: SoundCategory, val volume: Float, val pitch: Float) : ActionResult { +class SoundResult(val sound: String, private val soundCategory: SoundCategory, val volume: Float, val pitch: Float) : ActionResult { constructor(sound: Sound, soundCategory: SoundCategory, volume: Float, pitch: Float) : this(Registry.SOUNDS.getKey(sound)?.key!!, soundCategory, volume, pitch) - override fun execute(recipe: MultiblockRecipe<*>, craftingInventory: Inventory, sign: Sign) { - sign.world.playSound(sign.location, sound, soundCategory, volume, pitch) + override fun execute(context: RecipeExecutionContext) { + val entity = context.entity + entity.world.playSound(entity.location, sound, soundCategory, volume, pitch) } - } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 64fb7535a4..3526f332d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -15,12 +15,12 @@ import java.time.Duration interface ProgressMultiblock { val progressManager: ProgressManager - fun tickProgress(totalDuration: Duration) { + fun tickProgress(totalDuration: Duration): Boolean { val current = System.currentTimeMillis() val delta = Duration.ofMillis(current - progressManager.lastProgressTick) progressManager.lastProgressTick = current - progressManager.addProgress(totalDuration, delta) + return progressManager.addProgress(totalDuration, delta) } class ProgressManager(data: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt new file mode 100644 index 0000000000..908a206caf --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity + +/** + * Multiblock which processes multiblock recipes + **/ +interface RecipeEntity : ProgressMultiblock { + var currentRecipe: MultiblockRecipe<*> + + fun fetchInventories() + + fun getRecipe(): MultiblockRecipe<*>? { + return MultiblockRecipes.getRecipe(this as MultiblockEntity) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index e2100d5c9e..27a7a4be74 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -8,12 +8,6 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPres import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 @@ -22,12 +16,6 @@ import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.Po object Multiblocks : IonServerComponent() { private fun initMultiblocks() { // Recipe system multis - registerMultiblock(CentrifugeMultiblock) - registerMultiblock(CompressorMultiblock) - registerMultiblock(FabricatorMultiblock) - registerMultiblock(CircuitfabMultiblock) - registerMultiblock(PlatePressMultiblock) - registerMultiblock(GasFurnaceMultiblock) registerMultiblock(MissileLoaderMultiblock) registerMultiblock(AmmoLoaderMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt index 9f92810396..963e097511 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt @@ -1,29 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.type -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceEventHandler import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent interface FurnaceMultiblock { fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) - - /** - * Handle the execution of a recipe - **/ - fun handleRecipe(multiblock: Multiblock, event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isCancelled = true - - val recipe = MultiblockRecipes.getRecipe(multiblock, sign, furnace.inventory) ?: run { - event.burnTime = 500 - return - } - - if (recipe is FurnaceEventHandler) recipe.handleFurnaceEvent(event, furnace, sign) - recipe.execute(sign, furnace.inventory) - - furnace.cookTime = 0 - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 15712bf5bc..60d84bf4a5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -1,15 +1,20 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object AmmoLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object AmmoLoaderMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower = 250_000 override fun MultiblockShape.buildStructure() { @@ -132,7 +137,27 @@ object AmmoLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti line4 = null ) - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - handleRecipe(this, event, furnace, sign) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AmmoLoaderMultiblockEntity { + return AmmoLoaderMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } + + class AmmoLoaderMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, AmmoLoaderMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: AmmoLoaderMultiblock = AmmoLoaderMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index 0c8d4b66cd..d8cd9ccab9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -1,15 +1,20 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object MissileLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object MissileLoaderMultiblock : Multiblock(), NewPoweredMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { @@ -135,7 +140,27 @@ object MissileLoaderMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMu override val maxPower = 250_000 - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - handleRecipe(this, event, furnace, sign) - } + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): MissileLoaderMultiblockEntity { + return MissileLoaderMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } + + class MissileLoaderMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, MissileLoaderMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: MissileLoaderMultiblock = MissileLoaderMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index 34070bffd5..fa347568ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -1,15 +1,29 @@ package net.horizonsend.ion.server.features.multiblock.type.industry +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import org.bukkit.block.Furnace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object CentrifugeMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object CentrifugeMultiblock : Multiblock(), NewPoweredMultiblock { + override val name = "centrifuge" + + override val signText = createSignText( + line1 = "&6Centrifuge", + line2 = null, + line3 = null, + line4 = null + ) + override val maxPower: Int = 300_000 override fun MultiblockShape.buildStructure() { @@ -95,20 +109,27 @@ object CentrifugeMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti } } - override val name = "centrifuge" + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): CentrifugeMultiblockEntity { + return CentrifugeMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } - override val signText = createSignText( - line1 = "&6Centrifuge", - line2 = null, - line3 = null, - line4 = null - ) + class CentrifugeMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, CentrifugeMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: CentrifugeMultiblock = CentrifugeMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign, - ) { - handleRecipe(this, event, furnace, sign) + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt index 6eaafd3c04..ceec90eac5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt @@ -1,14 +1,19 @@ package net.horizonsend.ion.server.features.multiblock.type.industry +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import org.bukkit.block.Furnace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object CircuitfabMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object CircuitfabMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "circuitfab" override val signText = createSignText( @@ -71,11 +76,27 @@ object CircuitfabMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti } } - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign, - ) { - handleRecipe(this, event, furnace, sign) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): CircuitfabMultiblockEntity { + return CircuitfabMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } + + class CircuitfabMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, CircuitfabMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: CircuitfabMultiblock = CircuitfabMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt index 9dad988842..7c98d99b82 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt @@ -1,15 +1,20 @@ package net.horizonsend.ion.server.features.multiblock.type.industry +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import org.bukkit.block.Furnace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object CompressorMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object CompressorMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower = 300_000 override val name = "compressor" @@ -108,11 +113,27 @@ object CompressorMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti } } - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign, - ) { - handleRecipe(this, event, furnace, sign) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): CompressorMultiblockEntity { + return CompressorMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } + + class CompressorMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, CompressorMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: CompressorMultiblock = CompressorMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt index ead91eef02..501feac1bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt @@ -1,15 +1,20 @@ package net.horizonsend.ion.server.features.multiblock.type.industry +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import org.bukkit.block.Furnace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object FabricatorMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object FabricatorMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "fabricator" override val signText = createSignText( @@ -98,11 +103,27 @@ object FabricatorMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti } } - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign, - ) { - handleRecipe(this, event, furnace, sign) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): FabricatorMultiblockEntity { + return FabricatorMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } + + class FabricatorMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, FabricatorMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: FabricatorMultiblock = FabricatorMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt index 3118c07898..9a2f3b5654 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt @@ -1,19 +1,19 @@ package net.horizonsend.ion.server.features.multiblock.type.industry -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.gas.Gasses +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import org.bukkit.block.Furnace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.InventoryHolder -object GasFurnaceMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object GasFurnaceMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower: Int = 250_000 override val name = "gasfurnace" @@ -75,17 +75,27 @@ object GasFurnaceMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti } } - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - handleRecipe(this, event, furnace, sign) - - if (furnace.inventory.fuel?.customItem != CustomItemRegistry.GAS_CANISTER_EMPTY) return - - val inventoryHolder = furnace.block.getRelative(sign.getFacing().oppositeFace, 3).state as InventoryHolder - - val noFit = inventoryHolder.inventory.addItem(Gasses.EMPTY_CANISTER).values.isNotEmpty() + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): GasFurnaceMultiblockEntity { + return GasFurnaceMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } - if (noFit) return + class GasFurnaceMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, GasFurnaceMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: GasFurnaceMultiblock = GasFurnaceMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() - furnace.inventory.fuel = null + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt index a015fae7d7..c422135777 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt @@ -1,14 +1,19 @@ package net.horizonsend.ion.server.features.multiblock.type.industry +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import org.bukkit.block.Furnace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -object PlatePressMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object PlatePressMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower = 300_000 override fun MultiblockShape.buildStructure() { @@ -107,7 +112,27 @@ object PlatePressMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMulti line4 = null ) - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - handleRecipe(this, event, furnace, sign) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PlatePressMultiblockEntity { + return PlatePressMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } + + class PlatePressMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : SimplePoweredMultiblockEntity(data, manager, PlatePressMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { + override val poweredMultiblock: PlatePressMultiblock = PlatePressMultiblock + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } From cfd89d9f483ef1208c05d798d3950247dce4e953 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 17 Oct 2024 01:16:27 -0500 Subject: [PATCH 234/500] move ones I forgot to migrate --- .../server/features/multiblock/MultiblockRegistration.kt | 4 ++++ .../ion/server/features/multiblock/old/Multiblocks.kt | 6 ------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 35ebcd05fd..96509a16a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -8,6 +8,8 @@ import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMu import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop +import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 @@ -193,6 +195,8 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(CircuitfabMultiblock) registerMultiblock(PlatePressMultiblock) registerMultiblock(GasFurnaceMultiblock) + registerMultiblock(MissileLoaderMultiblock) + registerMultiblock(AmmoLoaderMultiblock) // Moreso powered multis than ship multis, could go in either spot tbh registerMultiblock(MiningLaserMultiblockTier1Top) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 27a7a4be74..d9b111c466 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -2,8 +2,6 @@ package net.horizonsend.ion.server.features.multiblock.old import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock @@ -15,10 +13,6 @@ import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.Po object Multiblocks : IonServerComponent() { private fun initMultiblocks() { - // Recipe system multis - registerMultiblock(MissileLoaderMultiblock) - registerMultiblock(AmmoLoaderMultiblock) - // Furnace start registerMultiblock(PowerFurnaceMultiblockTier1) registerMultiblock(PowerFurnaceMultiblockTier2) From 3734a57b1e6506920eeb1030468c92de6a22d24f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 18 Oct 2024 02:06:15 -0500 Subject: [PATCH 235/500] decomp visual upgrade --- .../server/features/machine/DecomposeTask.kt | 66 +++++++++++++++++++ .../weapon/projectile/ItemDisplayContainer.kt | 33 +++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt index c0343a241e..24cde7604e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt @@ -7,14 +7,19 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.ores.OldOreData import net.horizonsend.ion.server.features.starship.isFlyable +import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.ItemDisplayContainer import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Material.AIR +import org.bukkit.Material.GRAY_CONCRETE import org.bukkit.SoundCategory import org.bukkit.block.Block +import org.bukkit.block.BlockFace import org.bukkit.event.block.BlockBreakEvent import org.bukkit.inventory.ItemStack import org.bukkit.scheduler.BukkitRunnable +import org.bukkit.util.Vector +import org.joml.Vector3f class DecomposeTask( private val entity: DecomposerMultiblock.DecomposerEntity, @@ -26,6 +31,32 @@ class DecomposeTask( private var currentBlock: Block = entity.getOrigin() + private val displayItem = ItemStack(GRAY_CONCRETE) + + val rightDisplay = ItemDisplayContainer( + entity.world, + 0.25f, + entity.vec3i.toCenterVector(), + entity.structureDirection.rightFace.direction, + displayItem + ).apply { scale = Vector3f(0.25f, 0.25f, 1.0f) } + + val upDisplay = ItemDisplayContainer( + entity.world, + 0.25f, + entity.vec3i.toCenterVector(), + BlockFace.UP.direction, + displayItem + ).apply { scale = Vector3f(0.25f, 0.25f, 1.0f) } + + val forwardDisplay = ItemDisplayContainer( + entity.world, + 0.25f, + entity.vec3i.toCenterVector(), + entity.structureDirection.direction, + displayItem + ).apply { scale = Vector3f(0.25f, 0.25f, 1.0f) } + override fun run() { try { if (breakStrip()) return @@ -42,6 +73,10 @@ class DecomposeTask( override fun cancel() { super.cancel() + rightDisplay.remove() + upDisplay.remove() + forwardDisplay.remove() + entity.userManager.getUserPlayer()?.information("Decomposer broke $totalBlocksBroken blocks.") entity.userManager.clear() entity.currentTask = null @@ -117,6 +152,7 @@ class DecomposeTask( } } + updateDisplays() totalBlocksBroken++ iterationBroken++ } @@ -138,6 +174,36 @@ class DecomposeTask( return success } + private fun updateDisplays() { + val block = currentBlock + val origin = entity.getOrigin() + val right = entity.structureDirection.rightFace + + // + 1 to get one block inside the frame + val currentWidth = (right.modX * (block.x - origin.x)) + (right.modZ * (block.z - origin.z)) + 1 + val currentHeight = block.y - origin.y + 1 + val currentDepth = (entity.structureDirection.modX * (block.x - origin.x)) + (entity.structureDirection.modZ * (block.z - origin.z)) + 1 + + val heightOffset = Vector(0, currentHeight, 0) + val widthOffset = Vector(currentWidth * right.modX, 0, currentWidth * right.modZ) + val depthOffset = Vector(currentWidth * right.modX, currentHeight, currentWidth * right.modZ) + + // Up display comes out of the width defining bar + upDisplay.offset = widthOffset.toVector3f() + upDisplay.scale = Vector3f(0f, 0f, currentDepth.toFloat()) + upDisplay.update() + + // Right display comes out of the vertical bar + rightDisplay.offset = heightOffset.toVector3f() + upDisplay.scale = Vector3f(0f, 0f, currentDepth.toFloat()) + upDisplay.update() + + // Depth display comes from the intersection point of the 2 bars + forwardDisplay.offset = depthOffset.toVector3f() + forwardDisplay.scale = Vector3f(0f, 0f, currentDepth.toFloat()) + forwardDisplay.update() + } + private fun moveForward(): Boolean { val next = getNextBlock(currentBlock) ?: return false currentBlock = next diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ItemDisplayContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ItemDisplayContainer.kt index 39ac8f745c..ab009fb673 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ItemDisplayContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/ItemDisplayContainer.kt @@ -26,7 +26,7 @@ import java.util.UUID class ItemDisplayContainer( val world: World, - private val scale: Float, + initScale: Float, initPosition: Vector, initHeading: Vector, item: ItemStack @@ -55,7 +55,7 @@ class ItemDisplayContainer( field = value entity.setTransformation(com.mojang.math.Transformation( - Vector3f(0f), + Vector3f(offset), ClientDisplayEntities.rotateToFaceVector(value.toVector3f()), Vector3f(scale), Quaternionf() @@ -64,6 +64,35 @@ class ItemDisplayContainer( entity.transformationInterpolationDuration = 3 } + var scale: Vector3f = Vector3f(initScale) + set(value) { + field = value + + entity.setTransformation(com.mojang.math.Transformation( + Vector3f(offset), + ClientDisplayEntities.rotateToFaceVector(heading.toVector3f()), + Vector3f(scale), + Quaternionf() + )) + + entity.transformationInterpolationDuration = 3 + } + + var offset: Vector3f = Vector3f(0f) + set(value) { + field = value + + entity.setTransformation(com.mojang.math.Transformation( + Vector3f(value), + ClientDisplayEntities.rotateToFaceVector(heading.toVector3f()), + Vector3f(scale), + Quaternionf() + )) + + entity.transformationInterpolationDuration = 3 + } + + var itemStack: ItemStack = item set(value) { field = value From c4209d9b7437966890252b8b88b523b732a30cfb Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 27 Oct 2024 20:36:18 -0500 Subject: [PATCH 236/500] update forbidden blocks to use util functions --- .../command/admin/ForbiddenBlocksCommand.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ForbiddenBlocksCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ForbiddenBlocksCommand.kt index ef226150ff..311e6f5bbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ForbiddenBlocksCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ForbiddenBlocksCommand.kt @@ -16,9 +16,9 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getSelection -import net.horizonsend.ion.server.miscellaneous.utils.toVec3i -import net.minecraft.core.BlockPos import org.bukkit.entity.Player @CommandPermission("ion.command.admin.forbiddenblocks") @@ -37,7 +37,7 @@ object ForbiddenBlocksCommand : SLCommand() { for (blockVector in selection) { if (!mask.test(blockVector)) continue - new.add(BlockPos.asLong(blockVector.x(), blockVector.y(), blockVector.z())) + new.add(toBlockKey(blockVector.x(), blockVector.y(), blockVector.z())) } blocks.addAll(new) @@ -58,7 +58,7 @@ object ForbiddenBlocksCommand : SLCommand() { (mask as? AbstractExtentMask)?.extent = BukkitAdapter.adapt(sender.world) blocks.removeAll { - val pos = BlockPos.of(it) + val pos = toVec3i(it) selection.contains(pos.x, pos.y, pos.z) && mask.test(BlockVector3.at(pos.x, pos.y, pos.z)) } @@ -83,7 +83,7 @@ object ForbiddenBlocksCommand : SLCommand() { @Subcommand("show all") fun showAll(sender: Player) { - val blocks = sender.world.ion.detectionForbiddenBlocks.map { BlockPos.of(it).toVec3i() } + val blocks = sender.world.ion.detectionForbiddenBlocks.map(::toVec3i) sender.highlightBlocks(blocks, 40L) } @@ -92,9 +92,9 @@ object ForbiddenBlocksCommand : SLCommand() { val selection = sender.getSelection() ?: return sender.userError("You must make a selection!") val blocks = sender.world.ion.detectionForbiddenBlocks val intersect = blocks.filterTo(mutableSetOf()) { - val pos = BlockPos.of(it) - selection.contains(pos.x, pos.y, pos.z) - }.map { BlockPos.of(it).toVec3i() } + val (x, y, z) = toVec3i(it) + selection.contains(x, y, z) + }.map(::toVec3i) sender.highlightBlocks(intersect, 40L) } From 0b9e867bd5109b1fba649ca855d67dc633f92dc0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 27 Oct 2024 21:01:03 -0500 Subject: [PATCH 237/500] fix imports, mirrored multiblocks --- .../server/command/misc/AIOpponentCommand.kt | 2 +- .../command/starship/MiscStarshipCommands.kt | 2 +- .../module/combat/MultiTargetCombatModule.kt | 4 +-- .../combat/MultiTargetFrigateCombatModule.kt | 6 ++-- .../ai/module/misc/GravityWellModule.kt | 7 ++--- .../features/ai/module/misc/TrackingModule.kt | 6 ++-- .../features/ai/spawning/AISpawningUtils.kt | 2 +- .../features/ai/spawning/ships/SpawnedShip.kt | 2 +- .../spawner/scheduler/LocusScheduler.kt | 6 ++-- .../multiblock/MultiblockRegistration.kt | 6 ++-- .../type/autocrafter/AutoCrafterMultiblock.kt | 4 +-- .../autocrafter/AutoCrafterMultiblockTier3.kt | 2 +- .../type/misc/DisposalMultiblock.kt | 13 +++++---- .../mininglasers/MiningLaserMultiblock.kt | 1 - .../MiningLaserMultiblockTier1.kt | 28 +++++++++---------- .../MiningLaserMultiblockTier2.kt | 13 ++++----- .../MiningLaserMultiblockTier3.kt | 11 +++----- .../MiningLaserMultiblockTier4.kt | 14 ++++------ .../heavy/DoomsdayDeviceWeaponMultiblock.kt | 8 +++--- .../weapon/turret/CycleTurretMultiblock.kt | 6 ++-- .../DisintegratorBeamWeaponMultiblock.kt | 8 +++--- .../weapon/turret/LogisticTurretMultiblock.kt | 6 ++-- .../starship/movement/StarshipMovement.kt | 5 +--- .../primary/CycleTurretWeaponSubsystem.kt | 4 +-- .../DisintegratorBeamWeaponSubsystem.kt | 4 +-- .../primary/DoomsdayDeviceWeaponSubsystem.kt | 5 ++-- .../primary/LogisticTurretWeaponSubsystem.kt | 4 +-- .../projectile/CycleTurretProjectile.kt | 2 +- .../projectile/DoomsdayDeviceProjectile.kt | 4 +-- .../projectile/LogisticTurretProjectile.kt | 2 +- .../miscellaneous/registrations/Listeners.kt | 1 - 31 files changed, 87 insertions(+), 101 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/AIOpponentCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/AIOpponentCommand.kt index 3b5322f7fd..9ef5afb03c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/AIOpponentCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/AIOpponentCommand.kt @@ -21,7 +21,7 @@ import net.horizonsend.ion.server.features.starship.destruction.StarshipDestruct import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Bukkit import org.bukkit.entity.Player import java.util.UUID diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index 57254ab385..6df5d0efcc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -35,7 +35,7 @@ import net.horizonsend.ion.server.configuration.util.Pos import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.client.display.HudIcons import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblock -import net.horizonsend.ion.server.features.multiblock.type.navigationcomputer.NavigationComputerMultiblockBasic +import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblockBasic import net.horizonsend.ion.server.features.player.NewPlayerProtection.hasProtection import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand import net.horizonsend.ion.server.features.space.Space diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetCombatModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetCombatModule.kt index abcdf59bae..52a9fc28b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetCombatModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetCombatModule.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.control.controllers.ai.AICon import net.horizonsend.ion.server.features.starship.control.movement.AIControlUtils import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.block.BlockFace import org.bukkit.util.Vector import java.util.function.Supplier @@ -85,4 +85,4 @@ abstract class MultiTargetCombatModule(controller: AIController, val targetingSu AIControlUtils.setAutoWeapons(controller, weaponSet, target.getAutoTurretTarget()) } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetFrigateCombatModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetFrigateCombatModule.kt index 20565cd6d9..cca3a0a03e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetFrigateCombatModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/combat/MultiTargetFrigateCombatModule.kt @@ -3,12 +3,12 @@ package net.horizonsend.ion.server.features.ai.module.combat import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getDirection +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import net.horizonsend.ion.server.miscellaneous.utils.getDirection import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace import java.util.function.Supplier class MultiTargetFrigateCombatModule(controller: AIController, private val toggleRandomTargeting: Boolean = true, targetingSupplier: Supplier>) : MultiTargetCombatModule(controller, targetingSupplier) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/GravityWellModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/GravityWellModule.kt index 53c9e7c3ac..a11781747d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/GravityWellModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/GravityWellModule.kt @@ -2,11 +2,10 @@ package net.horizonsend.ion.server.features.ai.module.misc import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.Interdiction -import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.control.movement.StarshipCruising -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getDirection +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getDirection import java.util.function.Supplier class GravityWellModule( @@ -18,7 +17,7 @@ class GravityWellModule( override fun tick() { val target = targetingSupplier.get() - if (!canWellWhileCruising && (starship !is ActiveControlledStarship || StarshipCruising.isCruising(starship))) { + if (!canWellWhileCruising && StarshipCruising.isCruising(starship)) { starship.setIsInterdicting(false) return } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/TrackingModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/TrackingModule.kt index aa263239f9..a283beacd1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/TrackingModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/module/misc/TrackingModule.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.ai.module.misc import net.horizonsend.ion.common.utils.miscellaneous.squared import net.horizonsend.ion.server.features.ai.util.AITarget import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getDirection +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getDirection import org.apache.commons.collections4.queue.CircularFifoQueue import org.bukkit.util.Vector import java.util.concurrent.ThreadLocalRandom @@ -75,4 +75,4 @@ class TrackingModule( return movementSum.multiply(1.0 / trackDuration.toDouble()) } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt index 256495a81c..5c8fb454d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/AISpawningUtils.kt @@ -20,8 +20,8 @@ import net.horizonsend.ion.server.features.starship.modules.AISinkMessageFactory import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.blockplacement.BlockPlacement import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getLocationNear import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import net.horizonsend.ion.server.miscellaneous.utils.getLocationNear import net.horizonsend.ion.server.miscellaneous.utils.placeSchematicEfficiently import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.state.BlockState diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/ships/SpawnedShip.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/ships/SpawnedShip.kt index 91aa22a2e0..9cc0f12f55 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/ships/SpawnedShip.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/ships/SpawnedShip.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.ai.configuration.AITemplate import net.horizonsend.ion.server.features.ai.spawning.createAIShipFromTemplate import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController -import net.horizonsend.ion.server.miscellaneous.utils.getRadialRandomPoint +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRadialRandomPoint import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/spawner/scheduler/LocusScheduler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/spawner/scheduler/LocusScheduler.kt index 964b2b043a..eee40938a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/spawner/scheduler/LocusScheduler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ai/spawning/spawner/scheduler/LocusScheduler.kt @@ -9,9 +9,9 @@ import net.horizonsend.ion.server.features.ai.spawning.spawner.AISpawner import net.horizonsend.ion.server.features.nations.NationsMap.dynmapLoaded import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.active.ActiveStarships -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared -import net.horizonsend.ion.server.miscellaneous.utils.getLocationNear +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getLocationNear import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextColor import org.bukkit.Bukkit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 96509a16a3..de6d02f021 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -2,9 +2,6 @@ package net.horizonsend.ion.server.features.multiblock import com.google.common.collect.Multimap import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Bottom -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Side -import net.horizonsend.ion.server.features.multiblock.mininglasers.MiningLaserMultiblockTier4Top import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop @@ -93,6 +90,9 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Bottom import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Side import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4Top import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblockBasic import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 029cb6a32b..5481722ea2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -256,7 +256,7 @@ abstract class AutoCrafterMultiblock( } abstract class AutoCrafterMultiblockMirrored( - tierText: String, + tierText: Component, private val tierMaterial: Material, iterations: Int, ) : AutoCrafterMultiblock(tierText, tierMaterial, iterations) { @@ -292,7 +292,7 @@ abstract class AutoCrafterMultiblockMirrored( y(+0) { x(-2).anyPipedInventory() x(-1).endRod() - x(+0).anyType(Material.DISPENSER, Material.DROPPER) + x(+0).anyType(Material.DISPENSER, Material.DROPPER, alias = "Dispenser or Dropper") x(+1).endRod() x(+2).anyPipedInventory() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt index 0d23140c36..f7b0701bb4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblockTier3.kt @@ -8,6 +8,6 @@ object AutoCrafterMultiblockTier3 : AutoCrafterMultiblock(text("Tier 3", AQUA), override val maxPower: Int = 600_000 } -object AutoCrafterMultiblockTier3Mirrored : AutoCrafterMultiblockMirrored("&bTier 3", Material.DIAMOND_BLOCK, iterations = 6) { +object AutoCrafterMultiblockTier3Mirrored : AutoCrafterMultiblockMirrored(text("Tier 3", AQUA), Material.DIAMOND_BLOCK, iterations = 6) { override val maxPower: Int = 600_000 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt index ddba5370c5..1225df04a0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt @@ -20,7 +20,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import kotlin.math.roundToInt -object AbstractDisposalMultiblock : Multiblock(), NewPoweredMultiblock { +abstract class AbstractDisposalMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "incinerator" override var signText: Array = arrayOf( @@ -32,7 +32,7 @@ object AbstractDisposalMultiblock : Multiblock(), NewPoweredMultiblock= power) continue + if ((size * multiblock.powerConsumed) + (amountToClear * 3) >= power) continue amountToClear += size inventory.clear(i) } - powerStorage.removePower((powerConsumed * amountToClear).roundToInt()) + powerStorage.removePower((multiblock.powerConsumed * amountToClear).roundToInt()) } override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt index f6271da11d..cee937c1a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt @@ -25,7 +25,6 @@ abstract class MiningLaserMultiblock : Multiblock(), NewPoweredMultiblock = arrayOf( - Component.text("Mining ").color(NamedTextColor.DARK_GRAY) - .append(Component.text("Laser").color(NamedTextColor.GREEN)), - Component.text("Tier 1").color(NamedTextColor.AQUA), - Component.text(""), - Component.text("") + text("Mining ").color(DARK_GRAY).append(text("Laser").color(GREEN)), + text("Tier 1").color(NamedTextColor.AQUA), + text(""), + text("") ) + override fun getFirePointOffset(): Vec3i = Vec3i(+0, +3, +1) + override val maxPower: Int = 100000 override val beamOrigin = Triple(0, 3, 1) override val range: Double = 75.0 @@ -28,9 +32,6 @@ sealed class MiningLaserMultiblockTier1 : MiningLaserMultiblock() { object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { override val side = BlockFace.UP - override val mirrored = false - - override fun getFirePointOffset(): Vec3i = Vec3i(+0, +3, +1) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) override fun MultiblockShape.buildStructure() { @@ -110,9 +111,8 @@ object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { override val side = BlockFace.UP - override val mirrored = true - override fun getFirePointOffset(): Vec3i = Vec3i(+0, +3, -2) + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -191,7 +191,6 @@ object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { override val side = BlockFace.DOWN - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, -3, +1) override val outputOffset: Vec3i = Vec3i(-1, +1, 0) @@ -273,8 +272,8 @@ object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { override val side = BlockFace.DOWN - override val mirrored = true + override val outputOffset: Vec3i = Vec3i(+1, +1, 0) override fun getFirePointOffset(): Vec3i = Vec3i(+0, -3, -2) override fun MultiblockShape.buildStructure() { @@ -354,7 +353,6 @@ object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { object MiningLaserMultiblockTier1Side : MiningLaserMultiblockTier1() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, +5) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -439,9 +437,9 @@ object MiningLaserMultiblockTier1Side : MiningLaserMultiblockTier1() { object MiningLaserMultiblockTier1SideMirrored : MiningLaserMultiblockTier1() { override val side = BlockFace.UP - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, -5) + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -519,4 +517,4 @@ object MiningLaserMultiblockTier1SideMirrored : MiningLaserMultiblockTier1() { } } } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt index 3b5dca7097..afce2e530f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt @@ -28,7 +28,6 @@ sealed class MiningLaserMultiblockTier2 : MiningLaserMultiblock() { object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, +5, +1) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -144,7 +143,8 @@ object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { override val side = BlockFace.UP - override val mirrored = true + + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun getFirePointOffset(): Vec3i = Vec3i(+0, +5, -2) @@ -259,7 +259,6 @@ object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { override val side = BlockFace.DOWN - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, -5, +1) override val outputOffset: Vec3i = Vec3i(-1, +1, 0) @@ -375,9 +374,9 @@ object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { override val side = BlockFace.DOWN - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+0, -5, -2) + override val outputOffset: Vec3i = Vec3i(+1, +1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -490,7 +489,6 @@ object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { object MiningLaserMultiblockTier2Side : MiningLaserMultiblockTier2() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, +7) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -610,7 +608,8 @@ object MiningLaserMultiblockTier2Side : MiningLaserMultiblockTier2() { object MiningLaserMultiblockTier2SideMirrored : MiningLaserMultiblockTier2() { override val side = BlockFace.UP - override val mirrored = true + + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, -7) @@ -725,4 +724,4 @@ object MiningLaserMultiblockTier2SideMirrored : MiningLaserMultiblockTier2() { } } } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt index 47a050be1a..f99960e1dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt @@ -28,7 +28,6 @@ sealed class MiningLaserMultiblockTier3 : MiningLaserMultiblock() { object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, +2) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -272,9 +271,9 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { override val side = BlockFace.UP - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, -3) + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -515,7 +514,6 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { override val side = BlockFace.DOWN - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, +2) override val outputOffset: Vec3i = Vec3i(-1, +1, 0) @@ -759,9 +757,9 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { override val side = BlockFace.DOWN - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, -3) + override val outputOffset: Vec3i = Vec3i(+1, +1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -1002,7 +1000,6 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { object MiningLaserMultiblockTier3Side : MiningLaserMultiblockTier3() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(-1, +1, +8) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -1244,9 +1241,9 @@ object MiningLaserMultiblockTier3Side : MiningLaserMultiblockTier3() { object MiningLaserMultiblockTier3SideMirrored : MiningLaserMultiblockTier3() { override val side = BlockFace.UP - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+1, -1, -8) + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -1481,4 +1478,4 @@ object MiningLaserMultiblockTier3SideMirrored : MiningLaserMultiblockTier3() { } } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt index f0af14f02d..eb617a92cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt @@ -1,7 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.mininglasers +package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor @@ -28,7 +27,6 @@ sealed class MiningLaserMultiblockTier4 : MiningLaserMultiblock() { object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, +2) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -272,9 +270,9 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { override val side = BlockFace.UP - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, -3) + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -515,7 +513,6 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { override val side = BlockFace.DOWN - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, +2) override val outputOffset: Vec3i = Vec3i(-1, +1, 0) @@ -759,9 +756,9 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { override val side = BlockFace.DOWN - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, -3) + override val outputOffset: Vec3i = Vec3i(+1, +1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -1002,7 +999,6 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { object MiningLaserMultiblockTier4Side : MiningLaserMultiblockTier4() { override val side = BlockFace.UP - override val mirrored = false override fun getFirePointOffset(): Vec3i = Vec3i(-1, +1, +8) override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -1243,9 +1239,9 @@ object MiningLaserMultiblockTier4Side : MiningLaserMultiblockTier4() { object MiningLaserMultiblockTier4SideMirrored : MiningLaserMultiblockTier4() { override val side = BlockFace.UP - override val mirrored = true override fun getFirePointOffset(): Vec3i = Vec3i(+1, -1, -8) + override val outputOffset: Vec3i = Vec3i(+1, -1, 0) override fun MultiblockShape.buildStructure() { z(+0) { @@ -1479,4 +1475,4 @@ object MiningLaserMultiblockTier4SideMirrored : MiningLaserMultiblockTier4() { } } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/DoomsdayDeviceWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/DoomsdayDeviceWeaponMultiblock.kt index 2991ebc317..78ded27d7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/DoomsdayDeviceWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/DoomsdayDeviceWeaponMultiblock.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.heavy +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy -import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.DoomsdayDeviceWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt index 735ebd4da2..9057940608 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt @@ -1,14 +1,14 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.CycleTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.CycleTurretProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/DisintegratorBeamWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/DisintegratorBeamWeaponMultiblock.kt index b3ab17882b..0b0405f1aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/DisintegratorBeamWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/DisintegratorBeamWeaponMultiblock.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.DisintegratorBeamWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt index 64d9aa7b8e..94a70d9e0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt @@ -1,13 +1,13 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LogisticTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.LogisticTurretProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material.GRINDSTONE import org.bukkit.World import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt index ea8882a5d6..79eb398e3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt @@ -14,7 +14,6 @@ import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet import net.horizonsend.ion.server.features.starship.Starship -import net.horizonsend.ion.server.features.starship.StarshipType import net.horizonsend.ion.server.features.starship.TypeCategory import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship @@ -24,16 +23,15 @@ import net.horizonsend.ion.server.features.starship.event.EnterPlanetEvent import net.horizonsend.ion.server.features.starship.isFlyable import net.horizonsend.ion.server.features.starship.subsystem.misc.CryopodSubsystem import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.listener.misc.ProtectionListener import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.rectangle import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.horizonsend.ion.server.miscellaneous.utils.nms -import net.horizonsend.ion.server.miscellaneous.utils.rectangle import net.minecraft.world.level.block.state.BlockState import org.bukkit.Location import org.bukkit.World @@ -44,7 +42,6 @@ import org.bukkit.entity.Item import org.bukkit.entity.Player import org.bukkit.util.Vector import org.litote.kmongo.setValue -import kotlin.collections.set import kotlin.math.sqrt abstract class StarshipMovement(val starship: ActiveStarship, val newWorld: World? = null) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/CycleTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/CycleTurretWeaponSubsystem.kt index 7920b22578..b603875f35 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/CycleTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/CycleTurretWeaponSubsystem.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.CycleTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.CycleTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import java.util.concurrent.TimeUnit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DisintegratorBeamWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DisintegratorBeamWeaponSubsystem.kt index c1d9e94ee4..c7431dc371 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DisintegratorBeamWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DisintegratorBeamWeaponSubsystem.kt @@ -2,14 +2,14 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.common.utils.miscellaneous.randomDouble import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.DisintegratorBeamWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.DisintegratorBeamWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.DisintegratorBeamProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DoomsdayDeviceWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DoomsdayDeviceWeaponSubsystem.kt index 356a48f8f2..b082828c76 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DoomsdayDeviceWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/DoomsdayDeviceWeaponSubsystem.kt @@ -8,9 +8,9 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.DoomsdayDeviceProjectile import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints import net.horizonsend.ion.server.miscellaneous.utils.runnable -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.Location @@ -82,3 +82,4 @@ class DoomsdayDeviceWeaponSubsystem( return Component.text("Doomsday Device") } } + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LogisticTurretWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LogisticTurretWeaponSubsystem.kt index 2cba06f00d..bb06bb3fa9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LogisticTurretWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/primary/LogisticTurretWeaponSubsystem.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.starship.subsystem.weapon.primary import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.LogisticTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.LogisticTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import java.util.concurrent.TimeUnit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/CycleTurretProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/CycleTurretProjectile.kt index d825577939..ed8ef0b54e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/CycleTurretProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/CycleTurretProjectile.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.common.extensions.informationAction import net.horizonsend.ion.common.extensions.userErrorAction import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.StarshipWeapons -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.CycleTurretMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.CycleTurretMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/DoomsdayDeviceProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/DoomsdayDeviceProjectile.kt index 7cbfecaae1..cecaf5c23c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/DoomsdayDeviceProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/DoomsdayDeviceProjectile.kt @@ -7,8 +7,8 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.damager.EntityDamager import net.horizonsend.ion.server.features.starship.damager.PlayerDamager import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.iterateVector -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.iterateVector +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.FluidCollisionMode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/LogisticTurretProjectile.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/LogisticTurretProjectile.kt index 82409473e9..44e4608f0d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/LogisticTurretProjectile.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/projectile/LogisticTurretProjectile.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.control.controllers.ai.AIController import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.shield.ShieldSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.spherePoints +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.spherePoints import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.Location diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 22a5279c98..3411410a94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -85,7 +85,6 @@ val listeners: List = listOf( ActivePlayerController.Companion, TransportManager, PersonalTransporterManager, - TransportManager, GlobalNodeManager, MultiblockEntities, From e85b0ac21505c330af8a5755f17dcc2b9d1a03dd Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 2 Nov 2024 10:12:58 -0500 Subject: [PATCH 238/500] remove some unused functions --- .../features/space/data/CompletedSection.kt | 7 ++-- .../features/transport/old/Extractors.kt | 19 ----------- .../generators/space/SpaceGenerator.kt | 8 ++--- .../listener/misc/ProtectionListener.kt | 7 +--- .../utils/coordinates/Coordinates.kt | 32 ------------------- 5 files changed, 5 insertions(+), 68 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt index f5c0a43050..bd00d388d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/data/CompletedSection.kt @@ -3,8 +3,6 @@ package net.horizonsend.ion.server.features.space.data import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.BLOCKS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.PALETTE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component1 -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component2 import net.minecraft.core.BlockPos import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.chunk.LevelChunk @@ -54,9 +52,8 @@ data class CompletedSection(val y: Int, val palette: MutableList, val val section = levelChunk.sections[y - worldMin] - val (chunkX, chunkZ) = levelChunk.pos - val chunkAbsoluteX = chunkX.shl(4) - val chunkAbsoluteZ = chunkZ.shl(4) + val chunkAbsoluteX = levelChunk.pos.x.shl(4) + val chunkAbsoluteZ = levelChunk.pos.z.shl(4) val sectionAbsoluteY = (y - worldMin).shl(4) for (x in 0..15) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt index 7adff983f6..b3daf62383 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt @@ -9,7 +9,6 @@ import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.coordinates import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded @@ -20,14 +19,10 @@ import net.horizonsend.ion.server.miscellaneous.utils.ungzip import org.bukkit.Bukkit.shutdown import org.bukkit.Material import org.bukkit.World -import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.BlockState import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.DaylightDetector -import org.bukkit.event.EventPriority -import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.world.WorldLoadEvent import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.inventory.InventoryHolder @@ -57,20 +52,6 @@ object Extractors : IonServerComponent() { worldDataMap.keys.forEach { saveExtractors(it) } } - listen(priority = EventPriority.MONITOR, ignoreCancelled = true) { event -> - val block: Block = event.block - - if (block.type == EXTRACTOR_BLOCK) { - add(block.world, block.coordinates) - } - } - - listen(priority = EventPriority.MONITOR, ignoreCancelled = true) { event -> - val block: Block = event.block - - remove(block.world, block.coordinates) - } - listen { event -> loadExtractors(event.world) } listen { event -> unloadExtractors(event.world) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt index cc842263aa..1a24051c9e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/generation/generators/space/SpaceGenerator.kt @@ -11,8 +11,6 @@ import net.horizonsend.ion.server.features.world.generation.WorldGenerationManag import net.horizonsend.ion.server.features.world.generation.generators.interfaces.WorldGenerator import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.WeightedRandomList -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component1 -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component2 import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.readSchematic @@ -130,8 +128,6 @@ class SpaceGenerator( densityMultiplier: Double, callback: (chunkSeed: Long, chunkRandom: Random, maxHeight: Int, minHeight: Int, x: Int, y: Int, z: Int) -> T? ): List { - val (centreChunkX, centreChunkZ) = chunkPos - val radius = 10 val radiusSquared = radius * radius @@ -143,13 +139,13 @@ class SpaceGenerator( for (chunkXOffset in -radius..+radius) { val chunkXOffsetSquared = chunkXOffset * chunkXOffset - val chunkX = chunkXOffset + centreChunkX + val chunkX = chunkXOffset + chunkPos.x val startX = chunkX.shl(4) val startXDouble = startX.toDouble() for (chunkZOffset in -radius..+radius) { val chunkZOffsetSquared = chunkZOffset * chunkZOffset - val chunkZ = chunkZOffset + centreChunkZ + val chunkZ = chunkZOffset + chunkPos.z val startZ = chunkZ.shl(4) val startZDouble = startZ.toDouble() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt index 6aad8b4865..c170f33d00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt @@ -24,10 +24,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.action import net.horizonsend.ion.server.miscellaneous.utils.colorize import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component1 -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component2 -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component3 -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.component4 import net.horizonsend.ion.server.miscellaneous.utils.isPilot import net.horizonsend.ion.server.miscellaneous.utils.msg import org.bukkit.Location @@ -147,8 +143,7 @@ object ProtectionListener : SLEventListener() { if (isRegionDenied(player, location)) denied = true - val (world, x, y, z) = location - val shipContaining = DeactivatedPlayerStarships.getContaining(world, x.toInt(), y.toInt(), z.toInt()) + val shipContaining = DeactivatedPlayerStarships.getContaining(location.world, location.blockX, location.blockY, location.blockZ) // Need to also check for null if (shipContaining !is PlayerStarshipData?) return true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt index 3b5d4e1677..c4d734e6bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.miscellaneous.utils.coordinates import net.horizonsend.ion.common.utils.miscellaneous.d import net.horizonsend.ion.common.utils.miscellaneous.squared import net.minecraft.core.BlockPos -import net.minecraft.world.level.ChunkPos import org.bukkit.Bukkit import org.bukkit.Chunk import org.bukkit.Location @@ -26,19 +25,12 @@ import kotlin.math.roundToInt import kotlin.math.sin import kotlin.math.sqrt -val Block.coordinates: Vec3i get() = Vec3i(x, y, z) - fun Location.isInRange(location: Location, radius: Double): Boolean = distanceSquared(location) <= radius.squared() fun Location.add(x: Int, y: Int, z: Int): Location = add(x.toDouble(), y.toDouble(), z.toDouble()) fun Location.add(trio: Vec3i): Location = add(trio.x.toDouble(), trio.y.toDouble(), trio.z.toDouble()) fun Location.add(face: BlockFace): Location = add(face.modX, face.modY, face.modZ) -operator fun Location.component1(): World = this.world -operator fun Location.component2(): Double = this.x -operator fun Location.component3(): Double = this.y -operator fun Location.component4(): Double = this.z - fun BlockPos.toVec3i() = Vec3i(this.x, this.y, this.z) fun isValidYLevel(y: Int) = y in 0..Bukkit.getServer().worlds[0].maxHeight @@ -338,36 +330,12 @@ fun isInside(location: Location, extraChecks: Int): Boolean { return true } -fun BlockPos.toVector() = Vector(this.x, this.y, this.z) - fun BlockPos.toLocation(world: World?) = Location(world, this.x.toDouble(), this.y.toDouble(), this.z.toDouble()) fun Location.toBlockPos() = BlockPos(this.x.roundToInt(), this.y.roundToInt(), this.z.roundToInt()) fun Location.toVector3f(): Vector3f = Vector3f(this.x.toFloat(), this.y.toFloat(), this.z.toFloat()) -operator fun BlockPos.component1(): Int = this.x - -operator fun BlockPos.component2(): Int = this.y - -operator fun BlockPos.component3(): Int = this.z - -operator fun BlockPos.minus(other: BlockPos) = BlockPos(this.x - other.x, this.y - other.y, this.z - other.z) - -operator fun Triple.minus(other: Triple) = Triple(this.first - other.first, this.second - other.second, this.third - other.third) - -operator fun ChunkPos.component1(): Int = this.x - -operator fun ChunkPos.component2(): Int = this.z - -fun Vector.toBlockPos() = BlockPos(this.x.roundToInt(), this.y.roundToInt(), this.z.roundToInt()) - -fun getChunkSection(minHeight: Int, maxHeight: Int, y: Int): Int { - check(y in minHeight..maxHeight) - - return (y - minHeight).shr(4) -} - fun vectorToBlockFace(vector: Vector, includeVertical: Boolean = false): BlockFace { val x = vector.x val z = vector.z From 2bd74e201400afe61e2385c5ab09c5d8c399da29 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 2 Nov 2024 14:13:19 -0500 Subject: [PATCH 239/500] Undo simple multiblock entity --- .../server/features/machine/AreaShields.kt | 2 +- .../multiblock/entity/MultiblockEntity.kt | 14 ++--- .../type/fluids/BasicFluidStoringEntity.kt | 2 +- .../type/power/PoweredMultiblockEntity.kt | 4 +- .../power/SimplePoweredMultiblockEntity.kt | 45 --------------- .../type/ammo/AmmoLoaderMultiblock.kt | 29 ++++++++-- .../type/ammo/MissileLoaderMultiblock.kt | 29 ++++++++-- .../type/autocrafter/AutoCrafterMultiblock.kt | 43 +++++++++++--- .../defense/passive/areashield/AreaShield.kt | 47 +++++++++++----- .../multiblock/type/drills/DrillMultiblock.kt | 54 ++++++++++++------ .../farming/harvester/HarvesterMultiblock.kt | 47 +++++++++++++--- .../type/farming/planter/PlanterMultiblock.kt | 47 +++++++++++++--- .../type/fluid/ElectrolysisMultiblock.kt | 6 +- .../collector/PipedGasCollectorMultiblock.kt | 3 +- .../type/industry/CentrifugeMultiblock.kt | 29 ++++++++-- .../type/industry/CircuitfabMultiblock.kt | 29 ++++++++-- .../type/industry/CompressorMultiblock.kt | 29 ++++++++-- .../type/industry/FabricatorMultiblock.kt | 29 ++++++++-- .../type/industry/GasFurnaceMultiblock.kt | 29 ++++++++-- .../type/industry/PlatePressMultiblock.kt | 29 ++++++++-- .../type/misc/DecomposerMultiblock.kt | 29 ++++++++-- .../type/misc/DisposalMultiblock.kt | 32 ++++++++--- .../multiblock/type/misc/MobDefender.kt | 4 +- .../type/power/charger/ChargerMultiblock.kt | 52 ++++++++++++----- .../power/generator/GeneratorMultiblock.kt | 42 ++++++++++++-- .../type/power/storage/PowerBankMultiblock.kt | 48 ++++++++++++---- .../type/power/storage/PowerCellMultiblock.kt | 48 ++++++++++++---- .../type/printer/CarbonProcessorMultiblock.kt | 40 +++++++++++-- .../type/printer/PrinterMultiblock.kt | 42 ++++++++++++-- .../mininglasers/MiningLaserMultiblock.kt | 56 ++++++++++++++----- .../subsystem/misc/MiningLaserSubsystem.kt | 2 +- 31 files changed, 707 insertions(+), 234 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt index 60bbd1995a..81c0b78bfb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/AreaShields.kt @@ -31,7 +31,7 @@ object AreaShields : IonServerComponent() { val shields = location.world.ion.multiblockManager[AreaShield.AreaShieldEntity::class] return shields.filter { - val radius = it.poweredMultiblock.radius + explosionSize + val radius = it.multiblock.radius + explosionSize val shieldLoc = it.location return@filter shieldLoc.world == location.world && shieldLoc.isInRange(location, radius) && !it.removed diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 720dda1ece..3d2a355610 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -33,16 +33,16 @@ import org.bukkit.persistence.PersistentDataAdapterContext * @param structureDirection The direction this multiblock is oriented [from the origin] **/ abstract class MultiblockEntity( - var manager: MultiblockManager, + var manager: MultiblockManager, + open val multiblock: Multiblock, - var x: Int, - var y: Int, - var z: Int, - var world: World, + var x: Int, + var y: Int, + var z: Int, + var world: World, - var structureDirection: BlockFace + var structureDirection: BlockFace ): PDCSerializable { - abstract val multiblock: Multiblock private var lastRetrieved = System.currentTimeMillis() /** Gets the time since this value was last retrieved */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index 2e8fc0344a..a44d8a4604 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -25,7 +25,7 @@ abstract class BasicFluidStoringEntity( world: World, structureDirection: BlockFace, storage: InternalStorage -) : MultiblockEntity(manager, x, y, z, world, structureDirection), FluidStoringEntity { +) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { @Suppress("LeakingThis") override val capacities: Array = arrayOf( loadStoredResource(data, "main", Component.text("Main Storage"), NamespacedKeys.MAIN_STORAGE, storage) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 7806ed064b..56756e106e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -6,11 +6,11 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { - val poweredMultiblock: NewPoweredMultiblock<*> + val multiblock: NewPoweredMultiblock<*> val powerStorage: PowerStorage fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { - return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), poweredMultiblock.maxPower) + return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) } fun savePowerData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt deleted file mode 100644 index 205753d927..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredMultiblockEntity.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type.power - -import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataAdapterContext - -abstract class SimplePoweredMultiblockEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val multiblock: Multiblock, - x: Int, - y: Int, - z: Int, - world: World, - structureDirection: BlockFace, -) : MultiblockEntity(manager, x, y, z, world, structureDirection), PoweredMultiblockEntity { - override val powerStorage: PowerStorage = this.loadStoredPower(data) - protected abstract val displayHandler: TextDisplayHandler - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 60d84bf4a5..2ec9d9c79b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -3,12 +3,15 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -149,9 +152,11 @@ object AmmoLoaderMultiblock : Multiblock(), NewPoweredMultiblock() // can be multiple times per slot, so list, not set @@ -239,7 +249,7 @@ abstract class AutoCrafterMultiblock( inputInventory.getItem(index)!!.amount-- } } } finally { - if (basePower != power) { + if (basePower != power) { powerStorage.setPower(power) } else { // Nothing crafted, could be temporary resource shortage, pause for shorter time period @@ -248,9 +258,25 @@ abstract class AutoCrafterMultiblock( } } + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) - resetSign(sign, multiblock) + multiblock.signText.withIndex().forEach { sign.front().line(it.index, it.value.orEmpty()) } } } } @@ -261,6 +287,7 @@ abstract class AutoCrafterMultiblockMirrored( iterations: Int, ) : AutoCrafterMultiblock(tierText, tierMaterial, iterations) { override val mirrored = true + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index ebe90a899e..d904ca9903 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -5,12 +5,15 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -22,6 +25,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataAdapterContext import java.util.concurrent.TimeUnit abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { @@ -86,37 +90,50 @@ abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock< } class AreaShieldEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val poweredMultiblock: AreaShield, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, signDirection), LegacyMultiblockEntity { - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: AreaShield, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() override fun onLoad() { world.ion.multiblockManager.register(this) - super.onLoad() + + displayHandler.update() } override fun handleRemoval() { world.ion.multiblockManager.deregister(this) - super.handleRemoval() + + displayHandler.remove() } override fun onUnload() { world.ion.multiblockManager.deregister(this) - super.onUnload() + + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) } override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } - } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 1fcb0d3c60..383e694ff3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -8,11 +8,13 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity.UserManager -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager @@ -20,6 +22,7 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.player.CombatTimer +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils @@ -119,23 +122,19 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } class DrillMultiblockEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val poweredMultiblock: DrillMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - structureDirection: BlockFace, - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: DrillMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 5) override val userManager: UserManager = UserManager(data, persistent = true) - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() - override fun tick() { val player = userManager.getUserPlayer() ?: return disable() @@ -220,7 +219,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } private fun getBlocksToDestroy(): MutableList { - val toDestroy = getSquareRegion(4, 0, 0, poweredMultiblock.radius, 1) { + val toDestroy = getSquareRegion(4, 0, 0, multiblock.radius, 1) { it.type == Material.AIR || it.type == Material.BEDROCK } @@ -236,7 +235,28 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { userManager.saveUserData(store) - super.storeAdditionalData(store, adapterContext) + savePowerData(store) + } + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) + ).register() + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) } override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 960ce83cc8..22a3953a9b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -5,17 +5,19 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -31,6 +33,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.Ageable +import org.bukkit.persistence.PersistentDataAdapterContext abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { override val name: String = "harvester" @@ -110,22 +113,28 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I class HarvesterEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val poweredMultiblock: HarvesterMultiblock, + override val multiblock: HarvesterMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), StatusTickedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblockEntity { override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 20) - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() + private fun sleepWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } + override fun tick() { val inventory = getInventory(right = 0, up = 0, forward = 2) ?: return tickingManager.sleep(1000) var broken = 0 @@ -133,7 +142,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I val initialPower = powerStorage.getPower() if (initialPower == 0) return sleepWithStatus(text("No Power", RED), 500) - val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, poweredMultiblock.regionDepth) + val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) for (block in region) { val data = block.blockData @@ -151,7 +160,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I } } - if ((broken + 1) * poweredMultiblock.powerPerCrop > initialPower) { + if ((broken + 1) * multiblock.powerPerCrop > initialPower) { tickingManager.sleep(500) break } @@ -166,15 +175,35 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I break } - if (broken >= poweredMultiblock.tierNumber) break + if (broken >= multiblock.tierNumber) break } if (broken == 0) return sleepWithStatus(text("Sleeping", BLUE, ITALIC), 100) - powerStorage.removePower(broken * poweredMultiblock.powerPerCrop) + powerStorage.removePower(broken * multiblock.powerPerCrop) setStatus(text("Working", GREEN)) } + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index fb70374933..fb5869af33 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -5,17 +5,19 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE @@ -30,6 +32,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory +import org.bukkit.persistence.PersistentDataAdapterContext abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { override val name: String = "planter" @@ -101,22 +104,28 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int class PlanterEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val poweredMultiblock: PlanterMultiblock, + override val multiblock: PlanterMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), StatusTickedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() + private fun sleepWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } + override fun tick() { var planted = 0 val initialPower = powerStorage.getPower() @@ -127,7 +136,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int val seedItem = inventory.fuel ?: return sleepWithStatus(text("No Seeds", RED), 500) val crop = Crop.findBySeed(seedItem.type) ?: return sleepWithStatus( text("Unknown Crop", RED), 1000) - val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, poweredMultiblock.regionDepth) + val region = getRegionWithDimensions(-1 ,-1 ,4, 3, 1, multiblock.regionDepth) for (block in region) { if (block.type != Material.AIR) continue @@ -135,7 +144,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int if (!crop.canBePlanted(block)) continue if (block.lightFromBlocks < 7 && block.lightFromSky < 7) continue - if ((planted + 1) * poweredMultiblock.powerPerCrop > initialPower) { + if ((planted + 1) * multiblock.powerPerCrop > initialPower) { tickingManager.sleep(500) break } @@ -145,15 +154,35 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int crop.plant(block) - if (planted >= poweredMultiblock.tierNumber) break + if (planted >= multiblock.tierNumber) break } if (planted == 0) return sleepWithStatus(text("Sleeping", BLUE, ITALIC), 100) - powerStorage.removePower(planted * poweredMultiblock.powerPerCrop) + powerStorage.removePower(planted * multiblock.powerPerCrop) setStatus(text("Working", GREEN)) } + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 024d39953b..a7bf66ff80 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -213,14 +213,14 @@ object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock = arrayOf( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index fa347568ae..88767804ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -3,12 +3,15 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -121,9 +124,11 @@ object CentrifugeMultiblock : Multiblock(), NewPoweredMultiblock= power) continue + if ((size * this.multiblock.powerConsumed) + (amountToClear * 3) >= power) continue amountToClear += size inventory.clear(i) } - powerStorage.removePower((multiblock.powerConsumed * amountToClear).roundToInt()) + powerStorage.removePower((this.multiblock.powerConsumed * amountToClear).roundToInt()) + } + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) } override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 49aaea73ac..411ba0b637 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -94,9 +94,7 @@ object MobDefender : Multiblock(), EntityMultiblock, FurnaceMultiblock { protected abstract val tierMaterial: Material @@ -90,16 +94,18 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere } class ChargerEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val poweredMultiblock: ChargerMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - signDirection: BlockFace, - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, signDirection), LegacyMultiblockEntity { - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: ChargerMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + signDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() @@ -138,7 +144,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere return } - var multiplier = poweredMultiblock.powerPerSecond + var multiplier = multiblock.powerPerSecond multiplier /= item.amount if (item.amount * multiplier > power) return @@ -154,8 +160,28 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPowere event.burnTime = 20 } + override fun onLoad() { + displayHandler.update() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } - } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 4f33588c26..412fc95f66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -5,16 +5,19 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED @@ -24,6 +27,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory +import org.bukkit.persistence.PersistentDataAdapterContext abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock { override val name = "generator" @@ -59,22 +63,28 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M class GeneratorMultiblockEntity( data: PersistentMultiblockData, manager: MultiblockManager, - override val poweredMultiblock: GeneratorMultiblock, + override val multiblock: GeneratorMultiblock, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusMultiblockEntity, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() + private fun sleepWithStatus(status: Component, sleepTicks: Int) { + setStatus(status) + tickingManager.sleep(sleepTicks) + } + override fun tick() { val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return sleepWithStatus(text("No Furnace"), 250) @@ -87,7 +97,7 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M val fuelItem = furnaceInventory.fuel ?: return sleepWithStatus(text("No Fuel", RED), 100) val fuel = GeneratorFuel.getFuel(fuelItem) ?: return sleepWithStatus(text("Invalid Fuel", RED), 100) - val sleepTicks = (fuel.cooldown / poweredMultiblock.speed).toInt() + val sleepTicks = (fuel.cooldown / multiblock.speed).toInt() sleepWithStatus(text("Working", GREEN), sleepTicks) fuelItem.amount-- @@ -100,6 +110,26 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M powerStorage.addPower(fuel.power) } + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index b958c84a65..fa0345e9be 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -4,19 +4,23 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers.newMultiblockSignOverlay import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.persistence.PersistentDataAdapterContext abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { abstract val tierMaterial: Material @@ -108,20 +112,42 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM } class PowerBankEntity( - data: PersistentMultiblockData, - manager: MultiblockManager, - override val poweredMultiblock: PowerBankMultiblock, - x: Int, - y: Int, - z: Int, - world: World, - structureDirection: BlockFace - ) : SimplePoweredMultiblockEntity(data, manager, poweredMultiblock, x, y, z, world, structureDirection), LegacyMultiblockEntity { - override val displayHandler = newMultiblockSignOverlay( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: PowerBankMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + + private val displayHandler = newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) ).register() + override fun onLoad() { + displayHandler.update() + } + + override fun onUnload() { + displayHandler.remove() + } + + override fun handleRemoval() { + displayHandler.remove() + } + + override fun displaceAdditional(movement: StarshipMovement) { + displayHandler.displace(movement) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 0cc58fe295..83cbb533d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -3,15 +3,19 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataAdapterContext object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "powercell" @@ -57,20 +61,42 @@ object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { override val maxPower: Int = 30000 @@ -94,17 +98,23 @@ object CarbonProcessorMultiblock : Multiblock(), NewPoweredMultiblock { override val name: String = "printer" @@ -133,22 +137,28 @@ abstract class PrinterMultiblock : Multiblock(), NewPoweredMultiblock { override val name = "mininglaser" @@ -35,22 +39,28 @@ abstract class MiningLaserMultiblock : Multiblock(), NewPoweredMultiblock Date: Sat, 2 Nov 2024 14:24:02 -0500 Subject: [PATCH 240/500] fix decomp origin --- .../horizonsend/ion/server/features/machine/DecomposeTask.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt index 24cde7604e..46886fe2cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt @@ -29,7 +29,7 @@ class DecomposeTask( ) : BukkitRunnable() { private var totalBlocksBroken = 0 - private var currentBlock: Block = entity.getOrigin() + private var currentBlock: Block = entity.getBlockRelative(1, 1, 1) private val displayItem = ItemStack(GRAY_CONCRETE) From 593bdfcf7abaf862c32d12443d5d6922b32e66e5 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 2 Nov 2024 14:30:27 -0500 Subject: [PATCH 241/500] Add common interface for multiblocks with displays --- .../multiblock/entity/MultiblockEntity.kt | 2 ++ .../entity/type/DisplayMultiblockEntity.kt | 7 ++++++ .../manager/ChunkMultiblockManager.kt | 2 ++ .../multiblock/manager/MultiblockManager.kt | 3 +++ .../type/industry/FabricatorMultiblock.kt | 22 +++---------------- 5 files changed, 17 insertions(+), 19 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 3d2a355610..a272eefac7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA @@ -170,6 +171,7 @@ abstract class MultiblockEntity( this.structureDirection = movement.displaceFace(structureDirection) displaceAdditional(movement) + if (this is DisplayMultiblockEntity) this.displayHandler.displace(movement) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt new file mode 100644 index 0000000000..e4510f538a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler + +interface DisplayMultiblockEntity { + val displayHandler: TextDisplayHandler +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 7bb544133c..1f16b5a936 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.util.NetworkType @@ -103,6 +104,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag fun onUnload() { multiblockEntities.values.forEach { it.onUnload() + if (it is DisplayMultiblockEntity) it.displayHandler.remove() } MultiblockTicking.removeMultiblockManager(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 935cf022aa..b8c2db6173 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock @@ -45,6 +46,7 @@ abstract class MultiblockManager(val log: Logger) { multiblockEntities[entity.locationKey] = entity entity.onLoad() + if (entity is DisplayMultiblockEntity) entity.displayHandler.update() if (entity is SyncTickingMultiblockEntity) { syncTickingMultiblockEntities[entity.locationKey] = entity @@ -70,6 +72,7 @@ abstract class MultiblockManager(val log: Logger) { asyncTickingMultiblockEntities.remove(key) entity?.handleRemoval() + if (this is DisplayMultiblockEntity) this.displayHandler.remove() return entity } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt index df3afbac5d..576b6b38ee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt @@ -5,13 +5,13 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -118,11 +118,11 @@ object FabricatorMultiblock : Multiblock(), NewPoweredMultiblock Date: Sun, 3 Nov 2024 12:06:38 -0600 Subject: [PATCH 242/500] Remove most blockpos utils --- .../ion/server/command/misc/RegenerateCommand.kt | 10 ++++++---- .../type/tool/mods/tool/drill/VeinMinerMod.kt | 15 +++++++++------ .../features/ores/generation/OreGeneration.kt | 16 +++++++++------- .../ion/server/features/ores/storage/OreData.kt | 4 ++-- .../features/starship/StarshipDetection.kt | 4 ++-- .../server/miscellaneous/utils/Miscellaneous.kt | 1 - 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt index 551a16f8be..554ea71ae0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/RegenerateCommand.kt @@ -25,10 +25,12 @@ import net.horizonsend.ion.server.features.space.data.CompletedSection import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getSelection import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.audience.Audience -import net.minecraft.core.BlockPos import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.NbtIo import net.minecraft.nbt.NbtOps @@ -241,9 +243,9 @@ object RegenerateCommand : SLCommand() { for (i in 0 until stored.positions.size) { val key = stored.positions[i] - val x = BlockPos.getX(key) - val y = BlockPos.getY(key) - val z = BlockPos.getZ(key) + val x = getX(key) + val y = getY(key) + val z = getZ(key) val oreIndex = stored.oreIndexes[i].toInt() val ore = stored.orePalette[oreIndex] diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/tool/drill/VeinMinerMod.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/tool/drill/VeinMinerMod.kt index 220483c7ce..25e60dfd91 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/tool/drill/VeinMinerMod.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/tool/drill/VeinMinerMod.kt @@ -7,12 +7,15 @@ import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModif import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ModificationItem import net.horizonsend.ion.server.features.custom.items.type.tool.mods.general.AOEDMod import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.TextDecoration -import net.minecraft.core.BlockPos import org.bukkit.block.Block import org.bukkit.block.BlockFace import java.util.ArrayDeque @@ -46,7 +49,7 @@ class VeinMinerMod( val visited = mutableMapOf() // Jumpstart the queue by adding the origin block - val originKey = BlockPos.asLong(origin.x, origin.y, origin.z) + val originKey = toBlockKey(origin.x, origin.y, origin.z) visited[originKey] = origin queue.push(originKey) @@ -59,9 +62,9 @@ class VeinMinerMod( if (visited.count() > depth) break val key = queue.removeFirst() - val x = BlockPos.getX(key) - val y = BlockPos.getY(key) - val z = BlockPos.getZ(key) + val x = getX(key) + val y = getY(key) + val z = getZ(key) // Do not allow checking blocks larger than render distance val block = origin.world.getBlockAt(x, y, z) @@ -82,7 +85,7 @@ class VeinMinerMod( continue } - val key1 = BlockPos.asLong(adjacentX, adjacentY, adjacentZ) + val key1 = toBlockKey(adjacentX, adjacentY, adjacentZ) if (visited.containsKey(key1)) continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt index 065b443108..e926fd90f3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/generation/OreGeneration.kt @@ -12,7 +12,9 @@ import net.horizonsend.ion.server.features.ores.storage.OreData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ORE_DATA import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.minecraft.core.BlockPos +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import org.bukkit.Chunk import org.bukkit.ChunkSnapshot import org.bukkit.Material @@ -124,9 +126,9 @@ object OreGeneration : IonServerComponent() { val replacementIndex = data.replacedIndexes[index].toInt() val replaced = data.replacedPalette[replacementIndex] - val x = BlockPos.getX(position) - val y = BlockPos.getY(position) - val z = BlockPos.getZ(position) + val x = getX(position) + val y = getY(position) + val z = getZ(position) if (snapshot.getBlockData(x, y, z) == ore.blockData) { blockUpdates[position] = replaced.createBlockData() @@ -177,9 +179,9 @@ object OreGeneration : IonServerComponent() { val maxY = chunk.world.maxHeight blockUpdates.forEach { (position, data) -> - val x = BlockPos.getX(position) - val y = BlockPos.getY(position) - val z = BlockPos.getZ(position) + val x = getX(position) + val y = getY(position) + val z = getZ(position) if (y > maxY || y < minY) { log.warn("Attempted to place ore outside of build limit! Did the world height change?") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt index e151ba369c..0470f29ab4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/ores/storage/OreData.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.ores.storage import com.manya.pdc.base.array.StringArrayDataType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.minecraft.core.BlockPos +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Material import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer @@ -50,7 +50,7 @@ class OreData( replacedPalette.lastIndex } - val key = BlockPos.asLong(x, y, z) + val key = toBlockKey(x, y, z) positions += key oreIndexes += oreIndex.toByte() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt index e0c73282d0..4445291d3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipDetection.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.isConcrete import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox @@ -22,7 +23,6 @@ import net.kyori.adventure.audience.Audience import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration -import net.minecraft.core.BlockPos import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -136,7 +136,7 @@ object StarshipDetection : IonServerComponent() { } // Don't allow blocks that have been added to the forbidden blocks list - if (forbiddenBlocks.contains(BlockPos.asLong(x, y, z /* Modern block key TODO replace with function */))) { + if (forbiddenBlocks.contains(toBlockKey(x, y, z /* Modern block key */))) { continue } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt index 49b3537bee..e2b6f0eded 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Miscellaneous.kt @@ -7,7 +7,6 @@ import net.horizonsend.ion.server.command.admin.IonCommand import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.machine.AreaShields import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.kyori.adventure.audience.Audience import net.kyori.adventure.audience.ForwardingAudience import net.milkbowl.vault.economy.Economy import net.minecraft.core.BlockPos From 887e0869fb602d717190487ce5bc864925c8cf21 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 13:31:20 -0600 Subject: [PATCH 243/500] migrate power furnaces --- .../multiblock/MultiblockRegistration.kt | 7 + .../features/multiblock/old/Multiblocks.kt | 8 -- .../powerfurnace/PowerFurnaceMultiblock.kt | 132 +++++++++++++++--- 3 files changed, 120 insertions(+), 27 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index de6d02f021..91f76cb7fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -61,6 +61,9 @@ import net.horizonsend.ion.server.features.multiblock.type.power.charger.Charger import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.generator.GeneratorMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 @@ -177,6 +180,10 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(AutoCrafterMultiblockTier2) registerMultiblock(AutoCrafterMultiblockTier3) + registerMultiblock(PowerFurnaceMultiblockTier1) + registerMultiblock(PowerFurnaceMultiblockTier2) + registerMultiblock(PowerFurnaceMultiblockTier3) + registerMultiblock(GeneratorMultiblockTier1) registerMultiblock(GeneratorMultiblockTier2) registerMultiblock(GeneratorMultiblockTier3) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index d9b111c466..c296b5350d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -7,17 +7,9 @@ import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMu import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock -import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier1 -import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier2 -import net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace.PowerFurnaceMultiblockTier3 object Multiblocks : IonServerComponent() { private fun initMultiblocks() { - // Furnace start - registerMultiblock(PowerFurnaceMultiblockTier1) - registerMultiblock(PowerFurnaceMultiblockTier2) - registerMultiblock(PowerFurnaceMultiblockTier3) - registerMultiblock(StandardAmmoPressMultiblock) registerMultiblock(GasCollectorMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index 82bc9b4d5b..c5ceffa9c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -1,16 +1,44 @@ package net.horizonsend.ion.server.features.multiblock.type.power.powerfurnace -import net.horizonsend.ion.server.features.machine.PowerMachines +import com.google.common.cache.CacheBuilder +import com.google.common.cache.CacheLoader +import com.google.common.cache.LoadingCache +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN +import net.kyori.adventure.text.format.NamedTextColor.RED +import net.minecraft.server.MinecraftServer +import net.minecraft.world.item.crafting.RecipeType +import org.bukkit.Bukkit import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Furnace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent +import org.bukkit.craftbukkit.v1_20_R3.block.CraftFurnaceFurnace +import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext +import java.util.Optional -abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { override val name = "powerfurnace" protected abstract val burnTime: Int @@ -52,22 +80,88 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), PowerSto } } - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - if (PowerMachines.getPower(sign) == 0) { - event.isCancelled = true - return + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PowerFurnaceMultiblockEntity { + return PowerFurnaceMultiblockEntity(data, manager, this, x, y, z, world, structureDirection) + } + + class PowerFurnaceMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: PowerFurnaceMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, PoweredMultiblockEntity, LegacyMultiblockEntity, + DisplayMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() + + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + override fun tick() { + if (powerStorage.getPower() == 0) { + sleepWithStatus(text("Insufficient Power", RED), 250) + return + } + + val furnace = getInventory(0, 0, 0)?.holder as? Furnace + + if (furnace == null) { + sleepWithStatus(text("Insufficient Power", RED), 250) + return + } + + if (furnace !is CraftFurnaceFurnace) return + val resultOption = smeltingRecipeCache[furnace] + + if (resultOption.isEmpty) { + sleepWithStatus(text("Invalid Recipe", RED), 250) + return + } + + powerStorage.removePower(30) + sleepWithStatus(text("Working...", GREEN), multiblock.burnTime) + + furnace.burnTime = multiblock.burnTime.toShort() + furnace.cookTime = 100.toShort() + furnace.update() } - val fuel = furnace.inventory.fuel ?: return - furnace.cookTime = 100.toShort() - event.isCancelled = false - event.isBurning = false - event.burnTime = burnTime + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } - PowerMachines.removePower(sign, 30) + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } + + companion object { + val smeltingRecipeCache: LoadingCache> = CacheBuilder.newBuilder().build( + CacheLoader.from { furnace -> + requireNotNull(furnace) + val furnaceTile = furnace.tileEntity + + val level = Bukkit.getWorlds().first().minecraft + + // Get results for the recipe + MinecraftServer.getServer().recipeManager + .getRecipeFor(RecipeType.SMELTING, furnaceTile, level) + .map { + println("Recipe holder: $it") + println("Recipe: ${it.value}") + val b = it.value.assemble(furnaceTile, level.registryAccess()) + println("B: $b") + CraftItemStack.asBukkitCopy(b) + } + } + ) + } } } From fc694615ee8d442bb8c55795e2c69a08427365ab Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 14:37:36 -0600 Subject: [PATCH 244/500] migrate item splitter --- .../multiblock/MultiblockRegistration.kt | 2 + .../features/multiblock/old/Multiblocks.kt | 4 - .../type/misc/ItemSplitterMultiblock.kt | 199 ++++++++---------- 3 files changed, 91 insertions(+), 114 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 91f76cb7fa..5ffe638010 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -42,6 +42,7 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultib import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock @@ -313,6 +314,7 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(DecomposerMultiblock) // Misc + registerMultiblock(ItemSplitterMultiblock) registerMultiblock(DisconnectedDockingTubeMultiblock) registerMultiblock(ConnectedDockingTubeMultiblock) registerMultiblock(CryoPodMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index c296b5350d..94cf8a2c02 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPres import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock object Multiblocks : IonServerComponent() { private fun initMultiblocks() { @@ -15,9 +14,6 @@ object Multiblocks : IonServerComponent() { registerMultiblock(GasCollectorMultiblock) registerMultiblock(VentMultiblock) registerMultiblock(GasPowerPlantMultiblock) - // Furnace end - - registerMultiblock(ItemSplitterMultiblock) } private fun registerMultiblock(multiblock: Multiblock) {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt index 74360b8c50..0c03f05b83 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt @@ -3,33 +3,34 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SPLITTER_DIRECTION -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getStateSafe -import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.NamedTextColor.AQUA import net.kyori.adventure.text.format.NamedTextColor.YELLOW import net.kyori.adventure.text.format.TextDecoration -import org.bukkit.block.Container -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.sign.Side import org.bukkit.entity.Player -import org.bukkit.event.inventory.FurnaceBurnEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryHolder import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType.BOOLEAN -object ItemSplitterMultiblock : Multiblock(), FurnaceMultiblock, InteractableMultiblock { +object ItemSplitterMultiblock : Multiblock(), InteractableMultiblock, EntityMultiblock { override val name: String = "splitter" private fun formatText(text: String, vararg params: String) = template(text(text, AQUA), paramColor = YELLOW, useQuotesAroundObjects = false, *params) @@ -92,134 +93,112 @@ object ItemSplitterMultiblock : Multiblock(), FurnaceMultiblock, InteractableMul if (isBlacklist(sign)) { player.success("Switched sorter to whitelist!") - pdc.set(SPLITTER_DIRECTION, PersistentDataType.BOOLEAN, false) + pdc.set(SPLITTER_DIRECTION, BOOLEAN, false) sign.getSide(Side.FRONT).line(3, LEFT) } else { player.success("Switched sorter to blacklist!") - pdc.set(SPLITTER_DIRECTION, PersistentDataType.BOOLEAN, true) + pdc.set(SPLITTER_DIRECTION, BOOLEAN, true) sign.getSide(Side.FRONT).line(3, RIGHT) } sign.update() } - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - migrate(sign) - - event.isBurning = false - event.burnTime = 20 - - furnace.cookTime = (-1000).toShort() - - val filter = getBlacklist(sign) - - val isBlacklist = isBlacklist(sign) - - val inputInventory = getStorage(sign, inputInventory) ?: return - val filteredInventory = getStorage(sign, filteredInventory) ?: return - val remainderInventory = getStorage(sign, remainderInventory) ?: return - - if (isBlacklist) { - doFilter(inputInventory, filteredInventory, remainderInventory) { it?.filterContains(filter) == false } - } else { - doFilter(inputInventory, filteredInventory, remainderInventory) { it?.filterContains(filter) == true } - } + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): SplitterMultiblockEntity { + return SplitterMultiblockEntity(manager, x, y, z, world, structureDirection, data.getAdditionalDataOrDefault(SPLITTER_DIRECTION, BOOLEAN, true)) } - /** If the lambda returns true, it is put into the filtered inventory, if possible **/ - private fun doFilter(takeFrom: InventoryHolder, filtered: InventoryHolder, remainder: InventoryHolder, filter: (ItemStack?) -> Boolean) { - val sourceInventory = takeFrom.inventory - val destinationInventory = filtered.inventory - val remainderInventory = remainder.inventory - - for ((index, item: ItemStack?) in sourceInventory.withIndex()) { - if (!filter(item)) { - tryTransfer(index, sourceInventory, remainderInventory) - continue - } - - tryTransfer(index, sourceInventory, destinationInventory) - } + private fun isBlacklist(sign: Sign): Boolean { + return sign.persistentDataContainer.getOrDefault(SPLITTER_DIRECTION, BOOLEAN, true) } - private fun tryTransfer(index: Int, sourceInventory: Inventory, destination: Inventory) { - val item = sourceInventory.contents[index] ?: return + private val RIGHT_OLD = text("<-----", AQUA) + private val BLACKLIST_OLD = text("BLACKLIST", NamedTextColor.BLACK, TextDecoration.BOLD) - val result: Int = destination.addItem(item).values.firstOrNull()?.amount ?: 0 + private val previousBlacklistText = listOf( + BLACKLIST_OLD, + RIGHT_OLD + ) - if (result == 0) { - // no items remaining - sourceInventory.setItem(index, null) - } else { - // if the amount is different, update the item in the original slot - if (result != item.amount) { - sourceInventory.setItem(index, item.clone().apply { amount = result }) + class SplitterMultiblockEntity( + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + private var isBlacklist: Boolean + ) : MultiblockEntity(manager, ItemSplitterMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val tickingManager: TickingManager = TickingManager(interval = 20) + + override fun tick() { + val filterItems = getBlacklist() ?: return + + val inputInventory = getInventory(0, 1, 0) ?: return + val remainderInventory = getInventory(2, 1, 1) ?: return + val filteredInventory = getInventory(-2, 1, 1) ?: return + + if (isBlacklist) { + doFilter(inputInventory, filteredInventory, remainderInventory) { it?.filterContains(filterItems) == false } + } else { + doFilter(inputInventory, filteredInventory, remainderInventory) { it?.filterContains(filterItems) == true } } } - } - - private fun ItemStack.filterContains(filter: Collection): Boolean = filter.any { this.isSimilar(it) } - - private fun getStorage(sign: Sign, offset: Vec3i): Container? { - val (x, y, z) = offset - val facing = sign.getFacing() - val right = facing.rightFace - - val absoluteOffset = Vec3i( - x = (right.modX * x) + (facing.modX * z), - y = y, - z = (right.modZ * x) + (facing.modZ * z) - ) - val absolute = absoluteOffset + Vec3i(sign.location) - - val (absoluteX, absoluteY, absoluteZ) = absolute - - return getStateSafe(sign.world, absoluteX, absoluteY, absoluteZ) as? Container - } - - private fun getBlacklist(sign: Sign): Collection { - val items = getStorage(sign, filterInventory)?.inventory ?: return listOf() - - return items.storageContents.filterNotNull() - } + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + store.addAdditionalData(SPLITTER_DIRECTION, BOOLEAN, isBlacklist) + } - private val inputInventory: Vec3i = Vec3i(0, 1, -1) + override fun loadFromSign(sign: Sign) { + val pdc = sign.persistentDataContainer + if (pdc.keys.contains(SPLITTER_DIRECTION)) return - private val filterInventory: Vec3i = Vec3i(0, 1, -3) + val line3 = sign.getSide(Side.FRONT).line(3) - private val remainderInventory: Vec3i = Vec3i(-2, 1, -2) + if (previousBlacklistText.contains(line3)) { + pdc.set(SPLITTER_DIRECTION, BOOLEAN, true) + sign.getSide(Side.FRONT).line(3, RIGHT) + return + } - private val filteredInventory: Vec3i = Vec3i(2, 1, -2) + pdc.set(SPLITTER_DIRECTION, BOOLEAN, false) + sign.getSide(Side.FRONT).line(3, LEFT) + sign.update() + } - private fun isBlacklist(sign: Sign): Boolean { - return sign.persistentDataContainer.getOrDefault(SPLITTER_DIRECTION, PersistentDataType.BOOLEAN, true) - } + fun getBlacklist(): List? { + val items = getInventory(0, 1, 1) ?: return null + return items.storageContents.filterNotNull() + } - private val RIGHT_OLD = text("<-----", AQUA) - private val LEFT_OLD = text("----->", AQUA) - private val BLACKLIST_OLD = text("BLACKLIST", NamedTextColor.BLACK, TextDecoration.BOLD) - private val WHITELIST_OLD = text("WHITELIST", NamedTextColor.WHITE, TextDecoration.BOLD) + /** If the lambda returns true, it is put into the filtered inventory, if possible **/ + private fun doFilter(sourceInventory: Inventory, destinationInventory: Inventory, remainderInventory: Inventory, filter: (ItemStack?) -> Boolean) { + for ((index, item: ItemStack?) in sourceInventory.withIndex()) { + if (!filter(item)) { + tryTransfer(index, sourceInventory, remainderInventory) + continue + } - private val previousBlacklistText = listOf( - BLACKLIST_OLD, - RIGHT_OLD - ) + tryTransfer(index, sourceInventory, destinationInventory) + } + } - /** Migrates an old splitter to the new PDC format / sign text */ - private fun migrate(sign: Sign) { - val pdc = sign.persistentDataContainer - if (pdc.keys.contains(SPLITTER_DIRECTION)) return + private fun tryTransfer(index: Int, sourceInventory: Inventory, destination: Inventory) { + val item = sourceInventory.contents[index] ?: return - val line3 = sign.getSide(Side.FRONT).line(3) + val result: Int = destination.addItem(item).values.firstOrNull()?.amount ?: 0 - if (previousBlacklistText.contains(line3)) { - pdc.set(SPLITTER_DIRECTION, PersistentDataType.BOOLEAN, true) - sign.getSide(Side.FRONT).line(3, RIGHT) - return + if (result == 0) { + // no items remaining + sourceInventory.setItem(index, null) + } else { + // if the amount is different, update the item in the original slot + if (result != item.amount) { + sourceInventory.setItem(index, item.clone().apply { amount = result }) + } + } } - pdc.set(SPLITTER_DIRECTION, PersistentDataType.BOOLEAN, false) - sign.getSide(Side.FRONT).line(3, LEFT) + private fun ItemStack.filterContains(filter: Collection): Boolean = filter.any { this.isSimilar(it) } } } From 958f34e03095b824274d39b411d91466339f1595 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 15:22:22 -0600 Subject: [PATCH 245/500] migrate ammo press --- .../multiblock/MultiblockRegistration.kt | 3 + .../features/multiblock/old/Multiblocks.kt | 3 - .../type/ammo/AmmoPressMultiblock.kt | 145 ++++++++++++------ .../power/generator/GeneratorMultiblock.kt | 29 +--- 4 files changed, 101 insertions(+), 79 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 5ffe638010..aee8429e85 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.Cthul import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 @@ -196,6 +197,8 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(CarbonProcessorMultiblock) + registerMultiblock(StandardAmmoPressMultiblock) + // Crafting registerMultiblock(CentrifugeMultiblock) registerMultiblock(CompressorMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 94cf8a2c02..791c95cdd5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -2,15 +2,12 @@ package net.horizonsend.ion.server.features.multiblock.old import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock object Multiblocks : IonServerComponent() { private fun initMultiblocks() { - registerMultiblock(StandardAmmoPressMultiblock) - registerMultiblock(GasCollectorMultiblock) registerMultiblock(VentMultiblock) registerMultiblock(GasPowerPlantMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index cfd503f5ac..5578b25213 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -4,20 +4,35 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.custo import net.horizonsend.ion.server.features.custom.items.attribute.AmmunitionRefillType import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.machine.PowerMachines +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity.StatusManager +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.kyori.adventure.text.Component.text import org.bukkit.Material -import org.bukkit.block.Furnace +import org.bukkit.Material.matchMaterial +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.inventory.InventoryHolder +import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext import java.lang.Integer.min -abstract class AmmoPressMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +abstract class AmmoPressMultiblock : Multiblock(), NewPoweredMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { @@ -123,56 +138,84 @@ abstract class AmmoPressMultiblock : Multiblock(), PowerStoringMultiblock, Furna line4 = null ) - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - val smelting = furnace.inventory.smelting - val fuel = furnace.inventory.fuel - val fuelCustomItem = fuel?.customItem - - if (PowerMachines.getPower(sign) == 0 || - smelting == null || - smelting.type != Material.PRISMARINE_CRYSTALS || - fuel == null || - fuelCustomItem == null - ) { - return - } + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): AmmoPressMultiblockEntity { + return AmmoPressMultiblockEntity(data, manager, this, x, y, z, world, structureDirection) + } + + class AmmoPressMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + override val multiblock: AmmoPressMultiblock, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity, + DisplayMultiblockEntity { + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickingManager = TickingManager(interval = 20) + override val statusManager: StatusManager = StatusManager() + + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() + + override fun tick() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return sleepWithStatus(text("No Furnace!"), 250) + val smelting = furnaceInventory.smelting + val fuel = furnaceInventory.fuel + val fuelCustomItem = fuel?.customItem + + if (powerStorage.getPower() == 0 || + smelting == null || + smelting.type != Material.PRISMARINE_CRYSTALS || + fuel == null || + fuelCustomItem == null + ) { + return + } if (!fuelCustomItem.hasComponent(CustomComponentTypes.AMMUNITION_STORAGE)) return val ammoComponent = fuelCustomItem.getComponent(CustomComponentTypes.AMMUNITION_STORAGE) val ammoRefillAttribute = fuelCustomItem.getAttributes(fuel).filterIsInstance().firstOrNull() ?: return - // deposit blaster/magazine into output if full - if (ammoComponent.getAmmo(fuel) == ammoComponent.balancingSupplier.get().capacity) { - val result = furnace.inventory.result - if (result != null && result.type != Material.AIR) return - furnace.inventory.result = event.fuel - furnace.inventory.fuel = null - return + // deposit blaster/magazine into output if full + if (ammoComponent.getAmmo(fuel) == ammoComponent.balancingSupplier.get().capacity) { + val result = furnaceInventory.result + if (result != null && result.type != Material.AIR) return + furnaceInventory.result = furnaceInventory.fuel + furnaceInventory.fuel = null + return + } + + // refill item check + val inventory = getInventory(0, 0, 6) ?: return + val typeRefill = matchMaterial(fuelCustomItem.getTypeRefill()) ?: return + if (!inventory.containsAtLeast(ItemStack(typeRefill), 1)) return + + tickingManager.sleep(200) + furnaceInventory.holder?.burnTime = 200 + furnaceInventory.holder?.update() + + val ammoToSet = min( + ammoComponent.balancingSupplier.get().capacity - ammoComponent.getAmmo(fuel), + ammoComponent.balancingSupplier.get().ammoPerRefill + ) + ammoComponent.setAmmo(fuel, fuelCustomItem, ammoComponent.getAmmo(fuel) + ammoToSet) + inventory.removeItemAnySlot(ItemStack(typeRefill)) + powerStorage.removePower(250) + powerStorage.removePower(250) + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) } - // refill item check - val direction = sign.getFacing().oppositeFace - val state = sign.block.getRelative(direction, 7).getState(false) - as? InventoryHolder ?: return - val inventory = state.inventory - val typeRefill = ammoRefillAttribute.type - if (!inventory.containsAtLeast(ItemStack(typeRefill), 1)) return - - event.isBurning = false - event.burnTime = 200 - furnace.cookTime = (-1000).toShort() - event.isCancelled = false - - val ammoToSet = min( - ammoComponent.balancingSupplier.get().capacity - ammoComponent.getAmmo(fuel), - ammoComponent.balancingSupplier.get().ammoPerRefill - ) - ammoComponent.setAmmo(fuel, fuelCustomItem, ammoComponent.getAmmo(fuel) + ammoToSet) - inventory.removeItemAnySlot(ItemStack(typeRefill)) - PowerMachines.removePower(sign, 250) + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 412fc95f66..225ae2c068 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -7,17 +7,17 @@ import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED @@ -69,22 +69,17 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity, DisplayMultiblockEntity { override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - override fun tick() { val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return sleepWithStatus(text("No Furnace"), 250) @@ -114,22 +109,6 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M savePowerData(store) } - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } From 801e9bbea488aff3d9016030137fa682aaffb1fd Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 15:34:55 -0600 Subject: [PATCH 246/500] migrate canister gas collector --- .../multiblock/MultiblockRegistration.kt | 3 + .../features/multiblock/old/Multiblocks.kt | 2 - .../CanisterGasCollectorMultiblock.kt | 157 ++++++++++++++++ .../fluid/collector/GasCollectorMultiblock.kt | 167 ------------------ 4 files changed, 160 insertions(+), 169 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index aee8429e85..bca54ed424 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -28,6 +28,7 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.planter.Plant import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall @@ -225,6 +226,8 @@ object MultiblockRegistration : IonServerComponent() { // Gas registerMultiblock(PipedGasCollectorMultiblock) + registerMultiblock(CanisterGasCollectorMultiblock, "GasCollectorMultiblock") + registerMultiblock(ElectrolysisMultiblock) registerMultiblock(FluidTankSmall) registerMultiblock(FluidTankMedium) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 791c95cdd5..4b1a0de880 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -4,11 +4,9 @@ import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock -import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.GasCollectorMultiblock object Multiblocks : IonServerComponent() { private fun initMultiblocks() { - registerMultiblock(GasCollectorMultiblock) registerMultiblock(VentMultiblock) registerMultiblock(GasPowerPlantMultiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt new file mode 100644 index 0000000000..3890c1b772 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt @@ -0,0 +1,157 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid.collector + +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.custom.items.GasCanister +import net.horizonsend.ion.server.features.gas.Gasses +import net.horizonsend.ion.server.features.gas.collection.CollectedGas +import net.horizonsend.ion.server.features.gas.type.Gas +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.leftFace +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.horizonsend.ion.server.miscellaneous.utils.weightedRandomOrNull +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack +import java.util.concurrent.ThreadLocalRandom +import kotlin.math.roundToInt + +object CanisterGasCollectorMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { + override val name = "gascollector" + + override val signText = createSignText( + line1 = "&cGas &6Collector", + line2 = null, + line3 = null, + line4 = null + ) + + override fun MultiblockShape.buildStructure() { + at(0, 0, 0).machineFurnace() + at(0, 0, 1).hopper() + } + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val available = Gasses.findAvailableGasses(sign.location).joinToString { it.identifier } + + player.information("Available gasses: $available") + } + + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): CanisterGasCollectorEntity { + return CanisterGasCollectorEntity(manager, x, y, z, world, structureDirection) + } + + class CanisterGasCollectorEntity( + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, CanisterGasCollectorMultiblock, x, y, z, world, structureDirection), AsyncTickingMultiblockEntity { + val configuration get() = IonServer.globalGassesConfiguration + override val tickingManager: TickingManager = TickingManager(20) + + override fun tickAsync() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return + if (!Gasses.isCanister(furnaceInventory.fuel)) return + + tickingManager.sleep(configuration.collectorTickInterval) + + furnaceInventory.holder?.burnTime = configuration.collectorTickInterval.toShort() + furnaceInventory.holder?.update() + + tickCollector(furnaceInventory) + } + + private fun tickCollector(furnaceInventory: FurnaceInventory) { + val hopperInventory = getInventory(0, 0, 1) ?: return + + // Weight gas output based on the number of lightning rods + val weight = arrayOf(structureDirection.rightFace, structureDirection.leftFace, BlockFace.UP, BlockFace.DOWN).count { face -> + getOrigin().getRelativeIfLoaded(face)?.type == Material.LIGHTNING_ROD + }.toDouble() / 4.0 + + val worldConfiguration = world.ion.configuration.gasConfiguration.gasses.shuffled(ThreadLocalRandom.current()) + val availableGasses = worldConfiguration.map { it.tryCollect(location) }.filter { it.amount > 0 } + + val random = availableGasses.weightedRandomOrNull { result: CollectedGas.CollectionResult -> result.amount.toDouble() } ?: return + + val delta = IonServer.globalGassesConfiguration.collectorTickInterval / 20L + val amount = (random.amount * weight) * (delta) + + Tasks.sync { tryHarvestGas(furnaceInventory, hopperInventory, random.gas, amount.roundToInt()) } + } + + private fun tryHarvestGas(furnaceInventory: FurnaceInventory, hopperInventory: Inventory, gas: Gas, amount: Int): Boolean { + val canisterItem = furnaceInventory.fuel ?: return false + val customItem = canisterItem.customItem ?: return false + + return when (customItem) { + CustomItems.GAS_CANISTER_EMPTY -> fillEmptyCanister(furnaceInventory, gas, amount) + is GasCanister -> fillGasCanister(canisterItem, furnaceInventory, hopperInventory, amount) // Don't even bother with the gas + else -> false + } + } + + private fun fillEmptyCanister(furnaceInventory: FurnaceInventory, gas: Gas, amount: Int): Boolean { + val newType = CustomItems.getByIdentifier(gas.containerIdentifier) as? GasCanister ?: return false + val newCanister = newType.createWithFill(amount) + + furnaceInventory.fuel = newCanister + + return true + } + + private fun fillGasCanister(canisterItem: ItemStack, furnaceInventory: FurnaceInventory, hopperInventory: Inventory, amount: Int): Boolean { + val type = canisterItem.customItem ?: return false + if (type !is GasCanister) return false + + val currentFill = type.getFill(canisterItem) + val newFill = currentFill + amount + + // If the canister would be filled + return if (newFill >= type.maximumFill) { + // Try to add a full canister to the hopper + val canAdd = hopperInventory.addItem(type.constructItemStack()) + + // If it can be added + if (canAdd.isEmpty()) { + // Clear it from the furnace + furnaceInventory.fuel = null + } else { + // Put a full one in its spot + furnaceInventory.fuel = type.constructItemStack() + + return false + } + + true + } else { + // If it's completely not filled, just fill it to the new level + type.setFill(canisterItem, newFill) + + true + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt deleted file mode 100644 index e87f602d9f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/GasCollectorMultiblock.kt +++ /dev/null @@ -1,167 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.fluid.collector - -import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.type.GasCanister -import net.horizonsend.ion.server.features.gas.Gasses -import net.horizonsend.ion.server.features.gas.collection.CollectedGas -import net.horizonsend.ion.server.features.gas.type.Gas -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.leftFace -import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.horizonsend.ion.server.miscellaneous.utils.weightedRandomOrNull -import org.bukkit.Material -import org.bukkit.block.Block -import org.bukkit.block.BlockFace -import org.bukkit.block.Furnace -import org.bukkit.block.Hopper -import org.bukkit.block.Sign -import org.bukkit.entity.Player -import org.bukkit.event.inventory.FurnaceBurnEvent -import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.ItemStack -import java.util.concurrent.ThreadLocalRandom -import kotlin.math.roundToInt - -object GasCollectorMultiblock : Multiblock(), FurnaceMultiblock, InteractableMultiblock { - override val name = "gascollector" - - override val signText = createSignText( - line1 = "&cGas &6Collector", - line2 = null, - line3 = null, - line4 = null - ) - - override fun MultiblockShape.buildStructure() { - at(0, 0, 0).machineFurnace() - at(0, 0, 1).hopper() - } - - val configuration = ConfigurationFiles.globalGassesConfiguration() - - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - event.isBurning = false - event.burnTime = 0 - event.isCancelled = true - val smelting = furnace.inventory.smelting - - if (smelting == null || smelting.type != Material.PRISMARINE_CRYSTALS) return - - if (!Gasses.isCanister(furnace.inventory.fuel)) return - - event.isBurning = false - event.burnTime = configuration.collectorTickInterval - furnace.cookTime = (-1000).toShort() - event.isCancelled = false - - Tasks.async { tickCollector(sign) } - } - - override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { - val available = Gasses.findAvailableGasses(sign.location).joinToString { it.identifier } - - player.information("Available gasses: $available") - } - - private fun tickCollector(collectorSign: Sign) { - val attachedFace = collectorSign.getFacing().oppositeFace - - val world = collectorSign.world - if (!world.isChunkLoaded((collectorSign.x + attachedFace.modX) shr 4, (collectorSign.z + attachedFace.modZ) shr 4)) return - - val furnace = collectorSign.block.getRelativeIfLoaded(attachedFace) ?: return - val hopper = furnace.getRelativeIfLoaded(attachedFace) ?: return - - // Weight gas output based on the number of lightning rods - val weight = arrayOf(attachedFace.rightFace, attachedFace.leftFace, BlockFace.UP, BlockFace.DOWN).count { face -> - val lightningRod = furnace.getRelativeIfLoaded(face) ?: return@count false - - lightningRod.type == Material.LIGHTNING_ROD - }.toDouble() / 4.0 - - val worldConfiguration = collectorSign.world.ion.configuration.gasConfiguration.gasses.shuffled(ThreadLocalRandom.current()) - val availableGasses = worldConfiguration.map { it.tryCollect(collectorSign.location) }.filter { it.amount > 0 } - - val random = availableGasses.weightedRandomOrNull { result: CollectedGas.CollectionResult -> - result.amount.toDouble() - } ?: return - - val delta = ConfigurationFiles.globalGassesConfiguration().collectorTickInterval / 20L - val amount = (random.amount * weight) * (delta) - - Tasks.sync { - tryHarvestGas(furnace, hopper, random.gas, amount.roundToInt()) - } - } - - private fun tryHarvestGas(furnaceBlock: Block, hopperBlock: Block, gas: Gas, amount: Int): Boolean { - val furnace = furnaceBlock.getState(false) as Furnace - val hopper = hopperBlock.getState(false) as Hopper - - val canisterItem = furnace.inventory.fuel ?: return false - val customItem = canisterItem.customItem ?: return false - - return when (customItem) { - CustomItemRegistry.GAS_CANISTER_EMPTY -> fillEmptyCanister(furnace, gas, amount) - - is GasCanister -> fillGasCanister(canisterItem, furnace, hopper, amount) // Don't even bother with the gas - - else -> false - } - } - - private fun fillEmptyCanister(furnace: Furnace, gas: Gas, amount: Int): Boolean { - val newType = CustomItemRegistry.getByIdentifier(gas.containerIdentifier) as? GasCanister ?: return false - val newCanister = newType.createWithFill(amount) - - furnace.inventory.fuel = newCanister - - return true - } - - private fun fillGasCanister(canisterItem: ItemStack, furnace: Furnace, hopper: Hopper, amount: Int): Boolean { - val type = canisterItem.customItem ?: return false - if (type !is GasCanister) return false - - val currentFill = type.getFill(canisterItem) - val newFill = currentFill + amount - - // If the canister would be filled - return if (newFill >= type.maximumFill) { - // Try to add a full canister to the hopper - val canAdd = hopper.inventory.addItem(type.constructItemStack()) - - // If it can be added - if (canAdd.isEmpty()) { - // Clear it from the furnace - furnace.inventory.fuel = null - } else { - // Put a full one in its spot - furnace.inventory.fuel = type.constructItemStack() - - return false - } - - true - } else { - // If it's completely not filled, just fill it to the new level - type.setFill(canisterItem, newFill) - - true - } - } -} From 673620e83ad08337a235cf9666caf337d9df3a9e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 15:37:59 -0600 Subject: [PATCH 247/500] migrate gas canister vent --- .../multiblock/MultiblockRegistration.kt | 2 + .../features/multiblock/old/Multiblocks.kt | 2 - .../type/fluid/CanisterVentMultiblock.kt | 76 +++++++++++++++++++ .../multiblock/type/fluid/VentMultiblock.kt | 54 ------------- 4 files changed, 78 insertions(+), 56 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index bca54ed424..9d075a2960 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -27,6 +27,7 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.Har import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.fluid.CanisterVentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock @@ -227,6 +228,7 @@ object MultiblockRegistration : IonServerComponent() { // Gas registerMultiblock(PipedGasCollectorMultiblock) registerMultiblock(CanisterGasCollectorMultiblock, "GasCollectorMultiblock") + registerMultiblock(CanisterVentMultiblock, "VentMultiblock") registerMultiblock(ElectrolysisMultiblock) registerMultiblock(FluidTankSmall) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt index 4b1a0de880..7df08c4dab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt @@ -3,11 +3,9 @@ package net.horizonsend.ion.server.features.multiblock.old import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock -import net.horizonsend.ion.server.features.multiblock.type.fluid.VentMultiblock object Multiblocks : IonServerComponent() { private fun initMultiblocks() { - registerMultiblock(VentMultiblock) registerMultiblock(GasPowerPlantMultiblock) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt new file mode 100644 index 0000000000..18a48daca0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt @@ -0,0 +1,76 @@ +package net.horizonsend.ion.server.features.multiblock.type.fluid + +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.custom.items.GasCanister +import net.horizonsend.ion.server.features.gas.Gasses +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.inventory.FurnaceInventory + +object CanisterVentMultiblock : Multiblock(), EntityMultiblock { + override val name: String = "vent" + + override val signText: Array = arrayOf( + Component.text() + .append(Component.text("Gas", NamedTextColor.RED)) + .append(Component.text(" Vent", NamedTextColor.GOLD)) + .build(), + null, + null, + null + ) + + override fun MultiblockShape.buildStructure() { + z(+0) { + y(-1) { + x(-1).lightningRod() + x(+0).ironBlock() + x(+1).lightningRod() + } + y(+0) { + x(-1).lightningRod() + x(+0).machineFurnace() + x(+1).lightningRod() + } + } + } + + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): CanisterVentMultiblockEntity { + return CanisterVentMultiblockEntity(manager, x, y, z, world, structureDirection) + } + + class CanisterVentMultiblockEntity( + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, CanisterGasCollectorMultiblock, x, y, z, world, structureDirection), AsyncTickingMultiblockEntity { + val configuration get() = IonServer.globalGassesConfiguration + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) + + override fun tickAsync() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return + + val fuel = furnaceInventory.fuel ?: return + val customItem = fuel.customItem ?: return + if (customItem !is GasCanister) return + + furnaceInventory.fuel = null + furnaceInventory.result = Gasses.EMPTY_CANISTER + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt deleted file mode 100644 index aaee0d0a6d..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/VentMultiblock.kt +++ /dev/null @@ -1,54 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type.fluid - -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.type.GasCanister -import net.horizonsend.ion.server.features.gas.Gasses -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.Material -import org.bukkit.block.Furnace -import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent - -object VentMultiblock : Multiblock(), FurnaceMultiblock { - override val name: String = "vent" - - override val signText: Array = arrayOf( - Component.text() - .append(Component.text("Gas", NamedTextColor.RED)) - .append(Component.text(" Vent", NamedTextColor.GOLD)) - .build(), - null, - null, - null - ) - - override fun MultiblockShape.buildStructure() { - z(+0) { - y(-1) { - x(-1).lightningRod() - x(+0).ironBlock() - x(+1).lightningRod() - } - y(+0) { - x(-1).lightningRod() - x(+0).machineFurnace() - x(+1).lightningRod() - } - } - } - - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - if (furnace.inventory.smelting?.type != Material.PRISMARINE_CRYSTALS) return - - val fuel = furnace.inventory.fuel ?: return - val customItem = fuel.customItem ?: return - if (customItem !is GasCanister) return - - furnace.inventory.fuel = null - furnace.inventory.result = Gasses.EMPTY_CANISTER - } -} From 59e50ca29016b10f2939d662ec4a72f643fd74a6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 15:52:31 -0600 Subject: [PATCH 248/500] migrate gas power plant, all old multis done --- .../multiblock/MultiblockRegistration.kt | 2 + .../features/multiblock/old/Multiblocks.kt | 13 -- .../type/fluid/GasPowerPlantMultiblock.kt | 191 ++++++++++-------- .../miscellaneous/registrations/Components.kt | 1 - 4 files changed, 104 insertions(+), 103 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 9d075a2960..f8177e6881 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -29,6 +29,7 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.planter.Plant import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.CanisterVentMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock +import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium @@ -229,6 +230,7 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(PipedGasCollectorMultiblock) registerMultiblock(CanisterGasCollectorMultiblock, "GasCollectorMultiblock") registerMultiblock(CanisterVentMultiblock, "VentMultiblock") + registerMultiblock(GasPowerPlantMultiblock) registerMultiblock(ElectrolysisMultiblock) registerMultiblock(FluidTankSmall) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt deleted file mode 100644 index 7df08c4dab..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/old/Multiblocks.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.old - -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock - -object Multiblocks : IonServerComponent() { - private fun initMultiblocks() { - registerMultiblock(GasPowerPlantMultiblock) - } - - private fun registerMultiblock(multiblock: Multiblock) {} -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt index fa9f96c37c..a1e5c4beb2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt @@ -1,33 +1,44 @@ package net.horizonsend.ion.server.features.multiblock.type.fluid import net.horizonsend.ion.server.configuration.ConfigurationFiles +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.Gasses.EMPTY_CANISTER import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer -import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getFacing -import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Effect -import org.bukkit.block.Container -import org.bukkit.block.Furnace +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent +import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext import kotlin.math.roundToInt -object GasPowerPlantMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMultiblock { +object GasPowerPlantMultiblock : Multiblock(), NewPoweredMultiblock { + override val maxPower: Int = 500000 override val name: String = "gaspowerplant" @@ -157,108 +168,110 @@ object GasPowerPlantMultiblock : Multiblock(), PowerStoringMultiblock, FurnaceMu } } - override fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) { - event.isBurning = false - event.burnTime = 0 - event.isCancelled = true + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): GasPowerPlantMultiblockEntity { + return GasPowerPlantMultiblockEntity(data, manager, x, y, z, world, structureDirection) + } - val inventory = furnace.inventory + class GasPowerPlantMultiblockEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, GasPowerPlantMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity, DisplayMultiblockEntity { + override val multiblock: GasPowerPlantMultiblock = GasPowerPlantMultiblock + override val powerStorage: PowerStorage = loadStoredPower(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - val fuelItem = inventory.smelting ?: return - val oxidizerItem = inventory.fuel ?: return + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), + StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + ).register() - val fuel = (fuelItem.customItem as? GasCanister) ?: return - val oxidizer = (oxidizerItem.customItem as? GasCanister) ?: return + override fun tick() { + val inventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return - val fuelType = fuel.gas - val oxidizerType = oxidizer.gas + val fuelItem = inventory.smelting ?: return + val oxidizerItem = inventory.fuel ?: return - if (fuelType !is GasFuel || oxidizerType !is GasOxidizer) return + val fuel = (fuelItem.customItem as? GasCanister) ?: return + val oxidizer = (oxidizerItem.customItem as? GasCanister) ?: return - val consumed = checkCanisters(sign, furnace, fuelItem, fuel, oxidizerItem, oxidizer) ?: return + val fuelType = fuel.gas + val oxidizerType = oxidizer.gas - if (PowerMachines.getPower(sign) <= maxPower) { - event.isBurning = true - furnace.burnTime = fuelType.cooldown.toShort() - furnace.cookTime = (-1000).toShort() + if (fuelType !is GasFuel || oxidizerType !is GasOxidizer) return - val power = (fuelType.powerPerUnit * oxidizerType.powerMultiplier) * consumed - PowerMachines.addPower(sign, power.roundToInt()) - } else { - furnace.world.playEffect(furnace.location.add(0.5, 0.5, 0.5), Effect.SMOKE, 4) - } - } + val consumed = checkCanisters(inventory, fuelItem, fuel, oxidizerItem, oxidizer) ?: return - private fun checkCanisters( - sign: Sign, - furnace: Furnace, - fuelItem: ItemStack, - fuelType: GasCanister, - oxidizerItem: ItemStack, - oxidizerType: GasCanister - ): Int? { - val fuelFill = fuelType.getFill(fuelItem) - val oxidizerFill = oxidizerType.getFill(oxidizerItem) + if (powerStorage.getPower() < maxPower) { + tickingManager.sleep(fuelType.cooldown) - // Burn fuel and oxidizer at 1:1 - // Cap consumption at 30 units - val consumed = minOf(ConfigurationFiles.globalGassesConfiguration().powerPlantConsumption, fuelFill, oxidizerFill) + inventory.holder?.burnTime = fuelType.cooldown.toShort() + inventory.holder?.update() - // God forbid it goes negative - if (fuelFill <= 0) { - clearEmpty(sign, furnace.inventory, fuelItem) - return null + val power = (fuelType.powerPerUnit * oxidizerType.powerMultiplier) * consumed + powerStorage.addPower(power.roundToInt()) + } else { + world.playEffect(location.toCenterLocation(), Effect.SMOKE, 4) + } } - if (oxidizerFill <= 0) { - clearEmpty(sign, furnace.inventory, oxidizerItem) - return null + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) } - if (fuelFill - consumed <= 0) { - // Replaces with empty, no need to set fill to zero - if (clearEmpty(sign, furnace.inventory, fuelItem)) return null - } else { - fuelType.setFill(fuelItem, fuelFill - consumed) + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) } - if (oxidizerFill - consumed <= 0) { - // Replaces with empty, no need to set fill to zero - if (clearEmpty(sign, furnace.inventory, oxidizerItem)) return null - } else { - oxidizerType.setFill(oxidizerItem, oxidizerFill - consumed) - } + private fun checkCanisters(furnace: FurnaceInventory, fuelItem: ItemStack, fuelType: GasCanister, oxidizerItem: ItemStack, oxidizerType: GasCanister): Int? { + val fuelFill = fuelType.getFill(fuelItem) + val oxidizerFill = oxidizerType.getFill(oxidizerItem) - return consumed - } + // Burn fuel and oxidizer at 1:1 + // Cap consumption at 30 units + val consumed = minOf(ConfigurationFiles.globalGassesConfiguration().powerPlantConsumption, fuelFill, oxidizerFill) - /** Returns whether the process should be aborted due to a problem **/ - private fun clearEmpty(sign: Sign, furnaceInventory: Inventory, itemStack: ItemStack): Boolean { - val discardChest = getStorage(sign, outputInventory) ?: return true - val noFit = discardChest.inventory.addItem(EMPTY_CANISTER).values.isNotEmpty() + // God forbid it goes negative + if (fuelFill <= 0) { + clearEmpty(furnace, fuelItem) + return null + } - if (noFit) return true + if (oxidizerFill <= 0) { + clearEmpty(furnace, oxidizerItem) + return null + } - furnaceInventory.remove(itemStack) - return false - } + if (fuelFill - consumed <= 0) { + // Replaces with empty, no need to set fill to zero + if (clearEmpty(furnace, fuelItem)) return null + } else { + fuelType.setFill(fuelItem, fuelFill - consumed) + } - private fun getStorage(sign: Sign, offset: Vec3i): Container? { - val (x, y, z) = offset - val facing = sign.getFacing() - val right = facing.rightFace + if (oxidizerFill - consumed <= 0) { + // Replaces with empty, no need to set fill to zero + if (clearEmpty(furnace, oxidizerItem)) return null + } else { + oxidizerType.setFill(oxidizerItem, oxidizerFill - consumed) + } - val absoluteOffset = Vec3i( - x = (right.modX * x) + (facing.modX * z), - y = y, - z = (right.modZ * x) + (facing.modZ * z) - ) + return consumed + } - val absolute = absoluteOffset + Vec3i(sign.location) - val (absoluteX, absoluteY, absoluteZ) = absolute + /** Returns whether the process should be aborted due to a problem **/ + private fun clearEmpty(furnaceInventory: Inventory, itemStack: ItemStack): Boolean { + val discardChest = getInventory(0, 0, 6) ?: return true + if (!LegacyItemUtils.canFit(discardChest, EMPTY_CANISTER)) return true - return getStateIfLoaded(sign.world, absoluteX, absoluteY, absoluteZ) as? Container + furnaceInventory.remove(itemStack) + return false + } } - - private val outputInventory: Vec3i = Vec3i(0, 0, -7) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 0af953f440..d20bd1ee0f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -140,7 +140,6 @@ val components: List = listOf( StationSieges, SolarSieges, - Multiblocks, MultiblockRecipes, MultiblockRegistration, MultiblockAccess, From 1617e705cdb4f7366a04d2b7254544980ae45dcb Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 16:11:59 -0600 Subject: [PATCH 249/500] Remove jank async block utils --- .../server/features/multiblock/Multiblock.kt | 48 ------------- .../multiblock/shape/BlockRequirement.kt | 3 - .../multiblock/shape/MultiblockShape.kt | 68 +------------------ .../features/multiblock/util/BlockSnapshot.kt | 52 -------------- ...syncBlockUtils.kt => asyncTileEntities.kt} | 58 +--------------- .../miscellaneous/utils/CoroutineUtils.kt | 10 +-- 6 files changed, 6 insertions(+), 233 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/{AsyncBlockUtils.kt => asyncTileEntities.kt} (60%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 6bc90f194e..827bff51d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -2,8 +2,6 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot -import net.horizonsend.ion.server.features.multiblock.util.getBukkitBlockState import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isValidYLevel import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded @@ -12,11 +10,9 @@ import net.kyori.adventure.text.Component import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import org.bukkit.Location -import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.block.data.type.WallSign import org.bukkit.block.sign.Side import org.bukkit.entity.Player @@ -78,37 +74,6 @@ abstract class Multiblock { return shape.checkRequirements(originBlock, inward, loadChunks, particles) } - suspend fun signMatchesStructureAsync(sign: Sign, loadChunks: Boolean = true) = signMatchesStructureAsync(sign.location, loadChunks) - suspend fun signMatchesStructureAsync(signLocation: Location, loadChunks: Boolean = true) = - signMatchesStructureAsync(signLocation.world, Vec3i(signLocation), loadChunks) - - suspend fun signMatchesStructureAsync( - world: World, - origin: Vec3i, - loadChunks: Boolean = true - ): Boolean { - val block = world.getBlockAt(origin.x, origin.y, origin.z) - val sign = (getBukkitBlockState(block, loadChunks) as? Sign) ?: return false - val inward = sign.getFacing().oppositeFace - - val x = origin.x + inward.modX - val y = origin.y + inward.modY - val z = origin.z + inward.modZ - - if (!isValidYLevel(y)) return false - - return blockMatchesStructureAsync(world, Vec3i(x, y, z), inward, loadChunks) - } - - suspend fun blockMatchesStructureAsync( - originWorld: World, - origin: Vec3i, - inward: BlockFace, - loadChunks: Boolean = true - ): Boolean { - return shape.checkRequirementsAsync(originWorld, origin, inward, loadChunks) - } - open fun matchesUndetectedSign(sign: Sign): Boolean { val line = sign.getSide(Side.FRONT).line(0) val content = (line as? TextComponent)?.content() ?: line.plainText() @@ -153,18 +118,5 @@ abstract class Multiblock { return Vec3i(sign.location).minus(Vec3i(face.modX, 0, face.modZ)) } - - /** - * Gets a multiblock's origin from a possible sign - * - * Returns null if the provided block snapshot is not a sign - **/ - fun getOrigin(sign: BlockSnapshot): Vec3i? { - val data = sign.data as? WallSign ?: return null - - val face = data.facing - - return Vec3i(sign.x, sign.y, sign.z).minus(Vec3i(face.modX, 0, face.modZ)) - } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 9b27928321..b66e2b1325 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -9,13 +9,10 @@ class BlockRequirement( val alias: String, var example: (BlockFace) -> BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, - private val asyncCheck: suspend (Block, BlockFace, Boolean) -> Boolean, private val dataCheck: (BlockData) -> Boolean ) { operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) - suspend fun checkAsync(block: Block, inward: BlockFace, loadChunks: Boolean) = asyncCheck.invoke(block, inward, loadChunks) - fun checkBlockData(data: BlockData) = dataCheck.invoke(data) fun setExample(blockData: BlockData): BlockRequirement { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 5b1168559d..ff6bee07b9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -7,7 +7,6 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUI import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING -import net.horizonsend.ion.server.features.multiblock.util.getBlockSnapshotAsync import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes @@ -43,7 +42,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.isWool import net.minecraft.world.level.block.AbstractFurnaceBlock import org.bukkit.Material import org.bukkit.Particle -import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData @@ -207,43 +205,6 @@ class MultiblockShape { } } - /** - * Checks all possible directions a multiblock face - * - * - **/ - suspend fun checkRequirementsAsync(originWorld: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { - val realOrigin = if (signCentered) origin + Vec3i(inward.oppositeFace.modX, 0, inward.oppositeFace.modZ) else origin - - // check all directions if ignoring direction - for (face in if (ignoreDirection) CARDINAL_BLOCK_FACES else listOf(inward)) { - if (checkRequirementsSpecificAsync(originWorld, realOrigin, face, loadChunks)) { - return true - } - } - - return false - } - - /** - * Checks a single direction of the multiblock - * - * TODO more documentation - **/ - suspend fun checkRequirementsSpecificAsync(world: World, origin: Vec3i, inward: BlockFace, loadChunks: Boolean): Boolean { - val blocks = getRequirementMap(inward).map { (offset, _) -> - val (x, y, z) = offset + origin - - offset to world.getBlockAt(x, y, z) - }.toMap() - - return getRequirementMap(inward).all { (offset, requirement) -> - val block = blocks[offset]!! - - requirement.checkAsync(block, inward, loadChunks) - } - } - private val allLocations = mutableSetOf() // used for checking for duplicates private fun addRequirement(right: Int, upward: Int, inward: Int, requirement: BlockRequirement) { @@ -269,7 +230,6 @@ class MultiblockShape { alias = type.toString(), example = { type.createBlockData() }, syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, - asyncCheck = { block, _, loadChunks -> getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type == type }, dataCheck = { type == it.material } ) @@ -283,12 +243,7 @@ class MultiblockShape { alias = alias, example = { types.first().createBlockData() }, syncCheck = { block, _, loadChunks -> - typeSet.contains(if (loadChunks) block.type else block.getTypeSafe()) - }, - asyncCheck = { block, _, loadChunks -> - val type = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.type - - typeSet.contains(type) + typeSet.contains(if (loadChunks) block.type else block.getTypeSafe() ?: return@BlockRequirement false) }, dataCheck = { typeSet.contains(it.material) } ) @@ -307,9 +262,6 @@ class MultiblockShape { getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } } === customBlock }, - asyncCheck = { block, _, loadChunks -> - getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.let { CustomBlocks.getByBlockData(it.data) } === customBlock - }, dataCheck = { CustomBlocks.getByBlockData(it) == customBlock } ) @@ -367,10 +319,6 @@ class MultiblockShape { val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) blockData is Slab && blockData.type == DOUBLE }, - asyncCheck = { block, _, loadChunks -> - val blockData: BlockData? = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.data - blockData is Slab && blockData.type == DOUBLE - }, dataCheck = { it is Slab && it.type == DOUBLE } ) ) @@ -386,13 +334,6 @@ class MultiblockShape { (blockData is Slab && blockData.type == DOUBLE) || TERRACOTTA_TYPES.contains(blockType) }, - asyncCheck = { block, _, loadChunks -> - val blockSnapshot = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks) - val blockData = blockSnapshot?.data - val blockType = blockSnapshot?.type - - (blockData is Slab && blockData.type == DOUBLE) || TERRACOTTA_TYPES.contains(blockType) - }, dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta } ) } @@ -527,13 +468,6 @@ class MultiblockShape { val facing = blockData.getValue(AbstractFurnaceBlock.FACING).blockFace return@check facing == inward.oppositeFace }, - asyncCheck = asyncCheck@{ block, inward, loadChunks -> - val blockData = getBlockSnapshotAsync(block.world, block.x, block.y, block.z, loadChunks)?.data as? Furnace ?: return@asyncCheck false - - if (blockData.material != Material.FURNACE) return@asyncCheck false - val facing = blockData.facing - return@asyncCheck facing == inward.oppositeFace - }, dataCheck = { it is Furnace } )) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt deleted file mode 100644 index 49e327c567..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/BlockSnapshot.kt +++ /dev/null @@ -1,52 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.util - -import kotlinx.coroutines.runBlocking -import net.horizonsend.ion.server.features.custom.blocks.CustomBlock -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import org.bukkit.Bukkit -import org.bukkit.ChunkSnapshot -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.Block -import org.bukkit.block.BlockState -import org.bukkit.block.data.BlockData - -class BlockSnapshot( - val world: World, - val x: Int, - val y: Int, - val z: Int, - val type: Material, - val data: BlockData -) { - val state: BlockState? get() { - return runBlocking { getBukkitBlockState(block, false) } - } - - val block: Block get() { - return world.getBlockAt(x, y, z) - } - - val customBlock: CustomBlock? get() = CustomBlocks.getByBlockData(data) - - val redstonePower: Int get() = block.blockPower - - companion object { - fun ChunkSnapshot.getBlockSnapshot(x: Int, y: Int, z: Int): BlockSnapshot? { - if (x shr 4 != getX()) return null - if (z shr 4 != getZ()) return null - - val chunkOriginX = getX().shl(4) - val chunkOriginZ = getZ().shl(4) - - val localX = x - chunkOriginX - val localZ = z - chunkOriginZ - - val world = Bukkit.getWorld(worldName)!! - - return BlockSnapshot(world, x, y, z, getBlockType(localX, y, localZ), getBlockData(localX, y, localZ)) - } - - fun Block.snapshot(): BlockSnapshot = BlockSnapshot(world, x, y, z, type, blockData) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt similarity index 60% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt index c6ae2db891..9bef0f3b56 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/AsyncBlockUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt @@ -5,22 +5,13 @@ import org.bukkit.block.BlockState as BukkitBlockState import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.future.asDeferred -import net.horizonsend.ion.server.features.multiblock.util.BlockSnapshot.Companion.getBlockSnapshot -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe -import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.core.BlockPos import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.block.entity.BlockEntity import net.minecraft.world.level.chunk.LevelChunk import org.bukkit.Bukkit -import org.bukkit.ChunkSnapshot import org.bukkit.Material import org.bukkit.World import org.bukkit.block.Block @@ -32,49 +23,6 @@ import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers import java.lang.reflect.Method -/** - * X and Z in real coordinates - **/ -suspend fun getChunkSnapshotAsync(world: World, x: Int, z: Int, loadChunks: Boolean = false): ChunkSnapshot? { - val chunk = if (loadChunks) { - world.getChunkAtAsync(x shr 4, z shr 4).asDeferred().await() - } else { - world.getChunkAtIfLoaded(x shr 4, z shr 4) ?: return null - } - - return chunk.chunkSnapshot -} - -/** Retrieves a snapshot of an async block */ -suspend fun getBlockSnapshotAsync(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = false): BlockSnapshot? { - val chunkX = x.shr(4) - val chunkZ = z.shr(4) - - if (world.isChunkLoaded(chunkX, chunkZ)) { - val type = getBlockTypeSafe(world, x, y, z) ?: return null - val data = getBlockDataSafe(world, x, y, z) ?: return null - - return BlockSnapshot(world, x, y, z, type, data) - } - - if (!loadChunks) return null - - val chunk = world.getChunkAtAsync(x, z).asDeferred().await() - val state = chunk.minecraft.getBlockState(x, y, z) - - return BlockSnapshot(world, x, y, z, state.bukkitMaterial, CraftBlockData.fromData(state)) -} - -/** Retrieves a snapshot of an async block */ -suspend fun getBlockSnapshotAsync(world: World, key: Long, loadChunks: Boolean = false): BlockSnapshot? { - val x = getX(key) - val y = getY(key) - val z = getZ(key) - return getChunkSnapshotAsync(world, x, z, loadChunks)?.getBlockSnapshot(x, y, z) -} - -suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } - fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { val serverLevel: ServerLevel = block.world.minecraft val blockPos = (block as CraftBlock).position @@ -96,9 +44,9 @@ fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { return chunk.getBlockEntity(blockPos) } -@Suppress("UNCHECKED_CAST") -fun getAndCastNMSTileEntity(block: Block, loadChunks: Boolean): T? = getNMSTileEntity(block, loadChunks) as? T - +/** + * Please don't use this unless it is necessary + **/ fun getBukkitBlockState(block: Block, loadChunks: Boolean) : BukkitBlockState? { // If this is the main thread, we don't need to do laggy reflection if (Bukkit.isPrimaryThread()) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/CoroutineUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/CoroutineUtils.kt index 2ff4c84a95..2130a3e3e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/CoroutineUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/CoroutineUtils.kt @@ -1,11 +1,5 @@ package net.horizonsend.ion.server.miscellaneous.utils -import kotlinx.coroutines.CoroutineScope -import org.bukkit.World -import org.bukkit.block.Block +import kotlinx.coroutines.Deferred -//TODO async block requests, updates, etc - -fun CoroutineScope.getBlock(world: World, x: Int, y: Int, z: Int): Block? { - return Tasks.getSyncBlocking { world.getBlockAt(x, y, z) } // TODO -} +suspend fun Map>.awaitAllValues(): Map = if (isEmpty()) mapOf() else mapValues { (_, v) -> v.await() } From cb0187199d2ebcea68a59afaccc96b69e5d867b3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 17:19:22 -0600 Subject: [PATCH 250/500] Update & reregister new multiblocks --- .../multiblock/MultiblockRegistration.kt | 17 ++++++++++++----- .../particleshield/EventShieldMultiblock.kt | 2 +- .../weapon/event/CthulhuBeamMultiblock.kt | 2 +- .../weapon/event/FireWaveWeaponMultiblock.kt | 8 ++++---- .../event/GazeStarshipWeaponMultiblock.kt | 8 ++++---- .../SkullThrowerStarshipWeaponMultiblock.kt | 8 ++++---- .../weapon/event/AbyssalGazeSubsystem.kt | 2 +- .../weapon/event/FireWaveWeaponSubsystem.kt | 2 +- .../weapon/event/FlamingSkullCannon.kt | 2 +- .../weapon/secondary/RocketWeaponSubsystem.kt | 1 - .../miscellaneous/registrations/Components.kt | 1 - 11 files changed, 29 insertions(+), 24 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index f8177e6881..9fe91213b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -2,9 +2,6 @@ package net.horizonsend.ion.server.features.multiblock import com.google.common.collect.Multimap import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockBottom -import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockSide -import net.horizonsend.ion.server.features.multiblock.starshipweapon.event.CthulhuBeamStarshipWeaponMultiblockTop import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock @@ -108,9 +105,15 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.canno import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon.PlasmaCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon.PulseCannonStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.CapitalBeamStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.CthulhuBeamStarshipWeaponMultiblockBottom +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.CthulhuBeamStarshipWeaponMultiblockSide +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.CthulhuBeamStarshipWeaponMultiblockTop +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.FireWaveWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.FlamethrowerStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.HorizontalPumpkinCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.GazeStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.MiniPhaserStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.PumpkinCannonStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.SkullThrowerStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event.SonicMissileWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.AIHeavyLaserStarshipWeaponMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy.AIPhaserStarshipWeaponMultiblock @@ -277,12 +280,15 @@ object MultiblockRegistration : IonServerComponent() { // Starship event weapons registerMultiblock(SonicMissileWeaponMultiblock) - registerMultiblock(HorizontalPumpkinCannonStarshipWeaponMultiblock) + registerMultiblock(PumpkinCannonStarshipWeaponMultiblock) registerMultiblock(CthulhuBeamStarshipWeaponMultiblockBottom) registerMultiblock(CthulhuBeamStarshipWeaponMultiblockTop) registerMultiblock(CthulhuBeamStarshipWeaponMultiblockSide) registerMultiblock(FlamethrowerStarshipWeaponMultiblock) registerMultiblock(CapitalBeamStarshipWeaponMultiblock) + registerMultiblock(FireWaveWeaponMultiblock) + registerMultiblock(GazeStarshipWeaponMultiblock) + registerMultiblock(SkullThrowerStarshipWeaponMultiblock) // Starship utilities registerMultiblock(BattleCruiserReactorMultiblock) @@ -315,6 +321,7 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(BoxShieldMultiblock) registerMultiblock(EventShieldMultiblock) + // Starship misc registerMultiblock(StandardGravityWellMultiblock) registerMultiblock(AmplifiedGravityWellMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt index ca699c72ed..0de708da44 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/EventShieldMultiblock.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.Sign import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt index 04a73b779f..efcf04ffa7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/CthulhuBeamMultiblock.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FireWaveWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FireWaveWeaponMultiblock.kt index 8d8a37abfb..92f1cb1521 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FireWaveWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/FireWaveWeaponMultiblock.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.FireWaveWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/GazeStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/GazeStarshipWeaponMultiblock.kt index 19eb2975fa..52f0f44cfd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/GazeStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/GazeStarshipWeaponMultiblock.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.AbyssalGazeSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SkullThrowerStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SkullThrowerStarshipWeaponMultiblock.kt index 75421e8c3e..0e405466cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SkullThrowerStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/event/SkullThrowerStarshipWeaponMultiblock.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.event +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.event -import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.FlamingSkullCannon -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/AbyssalGazeSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/AbyssalGazeSubsystem.kt index 081782b50b..d6296da4d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/AbyssalGazeSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/AbyssalGazeSubsystem.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.projectile.AbyssalGazeProjectile import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FireWaveWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FireWaveWeaponSubsystem.kt index 4664cd4e5d..e5e3bba603 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FireWaveWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FireWaveWeaponSubsystem.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces. import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.ManualWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.TestAOEProjectile -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.util.Vector diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamingSkullCannon.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamingSkullCannon.kt index a3464b6665..c072634d67 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamingSkullCannon.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/event/FlamingSkullCannon.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.CannonWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.event.projectile.FlamingSkullProjectile import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.HeavyWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.interfaces.PermissionWeaponSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Location import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt index aaa8b8b5f8..8a0a79bef1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/RocketWeaponSubsystem.kt @@ -15,7 +15,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace import net.kyori.adventure.text.Component import org.bukkit.block.BlockFace import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index d20bd1ee0f..133250e617 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -233,7 +233,6 @@ val components: List = listOf( ContactsJammingSidebar, CombatTimer, WorldEditListener, - TransportManager, DisplayHandlers, PlanetTeleportCooldown, MultiBlockDisplay, From aee139ba5faff4b60c3dbfef8aa2305459433742 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 18:06:46 -0600 Subject: [PATCH 251/500] Register mirrored variants --- .../multiblock/MultiblockRegistration.kt | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 9fe91213b3..30313a47d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultib import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPressMultiblock import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1Mirrored import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock @@ -16,8 +17,11 @@ import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areas import net.horizonsend.ion.server.features.multiblock.type.dockingtube.ConnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.dockingtube.DisconnectedDockingTubeMultiblock import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1 +import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier1Mirrored import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier2Mirrored import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.drills.DrillMultiblockTier3Mirrored import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.harvester.HarvesterMultiblockTier3 @@ -41,10 +45,12 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultibloc import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock @@ -71,10 +77,14 @@ import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBa import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerBankMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.power.storage.PowerCellMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.ArmorPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.CarbonProcessorMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock @@ -87,17 +97,29 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.H import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass3 import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.HyperdriveMultiblockClass4 import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1SideMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier1TopMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2SideMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier2TopMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3SideMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier3TopMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4Bottom +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4BottomMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4Side +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4SideMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4Top +import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblockTier4TopMirrored import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.HorizontalNavigationComputerMultiblockAdvanced import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblockBasic import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.VerticalNavigationComputerMultiblockAdvanced @@ -172,8 +194,11 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(ChargerMultiblockTier3) registerMultiblock(DrillMultiblockTier1) + registerMultiblock(DrillMultiblockTier1Mirrored) registerMultiblock(DrillMultiblockTier2) + registerMultiblock(DrillMultiblockTier2Mirrored) registerMultiblock(DrillMultiblockTier3) + registerMultiblock(DrillMultiblockTier3Mirrored) registerMultiblock(PlanterMultiblockTier1) registerMultiblock(PlanterMultiblockTier2) @@ -183,10 +208,14 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(HarvesterMultiblockTier3) registerMultiblock(DisposalMultiblock) + registerMultiblock(DisposalMultiblockMirrored) registerMultiblock(AutoCrafterMultiblockTier1) + registerMultiblock(AutoCrafterMultiblockTier1Mirrored) registerMultiblock(AutoCrafterMultiblockTier2) + registerMultiblock(AutoCrafterMultiblockTier1Mirrored) registerMultiblock(AutoCrafterMultiblockTier3) + registerMultiblock(AutoCrafterMultiblockTier1Mirrored) registerMultiblock(PowerFurnaceMultiblockTier1) registerMultiblock(PowerFurnaceMultiblockTier2) @@ -197,9 +226,13 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(GeneratorMultiblockTier3) registerMultiblock(CarbonPrinterMultiblock) + registerMultiblock(CarbonPrinterMultiblockMirrored) registerMultiblock(TechnicalPrinterMultiblock) + registerMultiblock(TechnicalPrinterMultiblockMirrored) registerMultiblock(GlassPrinterMultiblock) + registerMultiblock(GlassPrinterMultiblockMirrored) registerMultiblock(ArmorPrinterMultiblock) + registerMultiblock(ArmorPrinterMultiblockMirrored) registerMultiblock(CarbonProcessorMultiblock) @@ -217,17 +250,29 @@ object MultiblockRegistration : IonServerComponent() { // Moreso powered multis than ship multis, could go in either spot tbh registerMultiblock(MiningLaserMultiblockTier1Top) + registerMultiblock(MiningLaserMultiblockTier1TopMirrored) registerMultiblock(MiningLaserMultiblockTier1Bottom) + registerMultiblock(MiningLaserMultiblockTier1BottomMirrored) registerMultiblock(MiningLaserMultiblockTier1Side) + registerMultiblock(MiningLaserMultiblockTier1SideMirrored) registerMultiblock(MiningLaserMultiblockTier2Top) + registerMultiblock(MiningLaserMultiblockTier2TopMirrored) registerMultiblock(MiningLaserMultiblockTier2Bottom) + registerMultiblock(MiningLaserMultiblockTier2BottomMirrored) registerMultiblock(MiningLaserMultiblockTier2Side) + registerMultiblock(MiningLaserMultiblockTier2SideMirrored) registerMultiblock(MiningLaserMultiblockTier3Top) + registerMultiblock(MiningLaserMultiblockTier3TopMirrored) registerMultiblock(MiningLaserMultiblockTier3Bottom) + registerMultiblock(MiningLaserMultiblockTier3BottomMirrored) registerMultiblock(MiningLaserMultiblockTier3Side) + registerMultiblock(MiningLaserMultiblockTier3SideMirrored) registerMultiblock(MiningLaserMultiblockTier4Top) + registerMultiblock(MiningLaserMultiblockTier4TopMirrored) registerMultiblock(MiningLaserMultiblockTier4Bottom) + registerMultiblock(MiningLaserMultiblockTier4BottomMirrored) registerMultiblock(MiningLaserMultiblockTier4Side) + registerMultiblock(MiningLaserMultiblockTier4SideMirrored) // Gas registerMultiblock(PipedGasCollectorMultiblock) @@ -299,6 +344,7 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(OdometerMultiblock) registerMultiblock(LandingGearMultiblock) registerMultiblock(MagazineMultiblock) + registerMultiblock(MagazineMultiblockMirrored) registerMultiblock(NavigationComputerMultiblockBasic) registerMultiblock(VerticalNavigationComputerMultiblockAdvanced) From 60106e55f91edbce050308f988878c01a837650a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 18:25:20 -0600 Subject: [PATCH 252/500] Rename prepackaged to multiblock items tokens, full prepackaged implementation later --- .../server/command/admin/ItemDebugCommand.kt | 1 - .../server/command/misc/MultiblockCommand.kt | 19 +++++++++++++---- ...edMultiblockItem.kt => MultiblockToken.kt} | 21 +++++++------------ .../multiblock/MultiblockRegistration.kt | 6 ++++-- .../server/features/multiblock/PrePackaged.kt | 3 +++ .../SignlessStarshipWeaponMultiblock.kt | 2 +- 6 files changed, 31 insertions(+), 21 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/{PackagedMultiblockItem.kt => MultiblockToken.kt} (81%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt index 58b8e0e739..5070798dde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.command.admin import co.aikar.commands.InvalidCommandArgument import co.aikar.commands.PaperCommandManager import co.aikar.commands.annotation.CommandAlias -import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.information diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 6d11d3a73f..7c0cc321c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -7,12 +7,14 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.bracketed import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.displayBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket +import net.horizonsend.ion.server.features.custom.items.misc.MultiblockToken import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -25,13 +27,13 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration import org.bukkit.block.Block import org.bukkit.block.Sign +import org.bukkit.command.CommandSender import org.bukkit.entity.Player import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.EquipmentSlot import org.bukkit.util.Vector @CommandAlias("multiblock") -@CommandPermission("ion.multiblock") object MultiblockCommand : SLCommand() { override fun onEnable(manager: PaperCommandManager) { manager.commandContexts.registerContext(Multiblock::class.java) { c: BukkitCommandExecutionContext -> @@ -82,8 +84,7 @@ object MultiblockCommand : SLCommand() { @Subcommand("check") @CommandCompletion("@multiblocks") - @CommandPermission("ion.multiblock.check") - fun onCheck(sender: Player, lastMatch: Multiblock, x: Int, y: Int, z: Int) { + fun onCheck(sender: Player, lastMatch: Multiblock, x: Int, y: Int, z: Int) { val sign = sender.world.getBlockAt(x, y, z).state as? Sign ?: return sender.userError("Block at $x $y $z isn't a sign!") val face = sign.getFacing().oppositeFace @@ -115,7 +116,7 @@ object MultiblockCommand : SLCommand() { @Subcommand("place") @CommandCompletion("@multiblocks") - @CommandPermission("ion.multiblock.place") + @CommandPermission("ion.command.multiblock.place") fun onPlace(sender: Player, multiblock: Multiblock) { val shape = multiblock.shape.getRequirementMap(sender.facing) @@ -147,4 +148,14 @@ object MultiblockCommand : SLCommand() { sender.success("Placed ${multiblock.javaClass.simpleName}") } + + @Subcommand("give token") + @CommandCompletion("@multiblocks") + @CommandPermission("ion.command.multiblock.give") + fun onGivePrepackaged(sender: CommandSender, prePackagedType: Multiblock, recipient: Player?) { + val destination: Player = recipient ?: (sender as? Player ?: fail { "You must specify a player!" }) + + destination.inventory.addItem(MultiblockToken.constructFor(prePackagedType)) + sender.information("Added to inventory") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt similarity index 81% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index 13f52c9558..81b6cab503 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblockItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.custom.items.misc import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.Multiblock @@ -8,10 +9,10 @@ import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.PrePackaged.getPackagedData import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GRAY -import net.kyori.adventure.text.format.NamedTextColor.WHITE import net.kyori.adventure.text.format.TextDecoration.ITALIC import org.bukkit.Material import org.bukkit.entity.LivingEntity @@ -21,9 +22,9 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType import java.util.Locale -object PackagedMultiblockItem : CustomItem("PACKAGED_MULTIBLOCK") { +object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { override fun constructItemStack(): ItemStack { - val base = ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + val base = ItemStack(Material.PAPER).updateMeta { it.persistentDataContainer.set(CUSTOM_ITEM, PersistentDataType.STRING, identifier) it.displayName(text("Pre-Packaged Multiblock").decoration(ITALIC, false)) } @@ -36,16 +37,10 @@ object PackagedMultiblockItem : CustomItem("PACKAGED_MULTIBLOCK") { return base.updateMeta { PrePackaged.packageData(PrePackaged.PackagedMultiblockData(multiblock), it.persistentDataContainer) - it.displayName(text() - .decoration(ITALIC, false) - .color(WHITE) - .append(text("Pre-packaged ")) - .append(multiblock.getDisplayName()) - .build() - ) + it.displayName(ofChildren(multiblock.getDisplayName(), text(" Token")).itemName) it.lore(listOf( - text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", GRAY).decoration(ITALIC, false), - text("Variant: ${multiblock.javaClass.simpleName}", GRAY).decoration(ITALIC, false) + text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", GRAY).itemName, + text("Variant: ${multiblock.javaClass.simpleName}", GRAY).itemName )) } } @@ -77,6 +72,6 @@ object PackagedMultiblockItem : CustomItem("PACKAGED_MULTIBLOCK") { } PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData) - livingEntity.inventory.remove(itemStack) + itemStack.amount-- } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 30313a47d7..0136bca5ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -8,7 +8,9 @@ import net.horizonsend.ion.server.features.multiblock.type.ammo.StandardAmmoPres import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1 import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier1Mirrored import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2 +import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier2Mirrored import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3 +import net.horizonsend.ion.server.features.multiblock.type.autocrafter.AutoCrafterMultiblockTier3Mirrored import net.horizonsend.ion.server.features.multiblock.type.defense.active.AntiAirCannonBaseMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield10 import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield20 @@ -213,9 +215,9 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(AutoCrafterMultiblockTier1) registerMultiblock(AutoCrafterMultiblockTier1Mirrored) registerMultiblock(AutoCrafterMultiblockTier2) - registerMultiblock(AutoCrafterMultiblockTier1Mirrored) + registerMultiblock(AutoCrafterMultiblockTier2Mirrored) registerMultiblock(AutoCrafterMultiblockTier3) - registerMultiblock(AutoCrafterMultiblockTier1Mirrored) + registerMultiblock(AutoCrafterMultiblockTier3Mirrored) registerMultiblock(PowerFurnaceMultiblockTier1) registerMultiblock(PowerFurnaceMultiblockTier2) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 6caafde197..9af6a5c774 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomBlockItem import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded @@ -89,6 +90,8 @@ object PrePackaged { origin.world.playSound(block.location, soundGroup.placeSound, soundGroup.volume, soundGroup.pitch) } + if (data.multiblock is SignlessStarshipWeaponMultiblock<*>) return + // Add sign val signPosition = origin.getRelative(direction.oppositeFace, 1) val signData = Material.OAK_WALL_SIGN.createBlockData { signData -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt index e11c1953ba..13a77a1109 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/SignlessStarshipWeaponMultiblock.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsy import net.kyori.adventure.text.Component import org.bukkit.block.Sign -// TODO: Make signless multiblocks an actualStyle thing +// TODO: Make signless multiblocks an actual thing abstract class SignlessStarshipWeaponMultiblock : Multiblock(), SubsystemMultiblock { override val signText = arrayOf(null, null, null, null) From 62795a6af01f33a36cad6ddac7bb6af9ae05e07c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 18:59:08 -0600 Subject: [PATCH 253/500] give more multiblocks display names --- .../horizonsend/ion/common/utils/text/ComponentUtils.kt | 3 +++ .../features/multiblock/type/drills/DrillMultiblock.kt | 8 +++++++- .../multiblock/type/power/charger/ChargerMultiblock.kt | 8 +++++++- .../multiblock/type/power/storage/PowerBankMultiblock.kt | 8 +++++++- .../multiblock/type/power/storage/PowerCellMultiblock.kt | 6 +++++- .../NavigationComputerMultiblockAdvanced.kt | 8 +++++++- 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt index 267a5508ce..85287c8e37 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt @@ -22,12 +22,15 @@ import net.kyori.adventure.text.format.Style.style import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextDecoration import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer // Serialization /** Skip building the serializer */ val miniMessage = MiniMessage.miniMessage() +val legacyAmpersand = LegacyComponentSerializer.legacyAmpersand() + /** Serializes the component to minimessage format */ fun miniMessage(component: Component): String = miniMessage.serialize(component) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 383e694ff3..aaf08163f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -4,6 +4,8 @@ import net.horizonsend.ion.common.extensions.alertSubtitle import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.extensions.userErrorAction import net.horizonsend.ion.common.extensions.userErrorSubtitle +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks @@ -19,6 +21,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.player.CombatTimer @@ -30,6 +33,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox +import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.RED @@ -49,7 +53,7 @@ import java.util.EnumSet import java.util.UUID import kotlin.math.max -abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { +abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val radius: Int abstract val coolDown: Int @@ -65,6 +69,8 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M line4 = null ) + override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), text(" Drill")) + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { if (event.action != Action.RIGHT_CLICK_BLOCK) return val entity = getMultiblockEntity(sign) ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index bb08199498..270be379c6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.type.power.charger +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.custom.items.CustomItem @@ -14,9 +16,11 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -26,11 +30,13 @@ import org.bukkit.event.inventory.FurnaceBurnEvent import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext -abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock { +abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock, DisplayNameMultilblock { protected abstract val tierMaterial: Material protected abstract val powerPerSecond: Int + override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), Component.text(" Item Charger")) + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index fa0345e9be..180a492aa9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers.newMultiblockSignOverlay import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock @@ -11,9 +13,11 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace @@ -22,7 +26,7 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val tierMaterial: Material override val name = "powerbank" @@ -33,6 +37,8 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredM line4 = tierText ) + override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), Component.text(" Power Bank")) + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 83cbb533d4..95ee673a8d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -10,14 +10,16 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.kyori.adventure.text.Component import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext -object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock { +object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock, DisplayNameMultilblock { override val name = "powercell" override val signText = createSignText( @@ -27,6 +29,8 @@ object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock Date: Sun, 3 Nov 2024 19:36:56 -0600 Subject: [PATCH 254/500] undo decomp visuals --- .../server/features/machine/DecomposeTask.kt | 66 ------------------- 1 file changed, 66 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt index 46886fe2cc..9d22324002 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/DecomposeTask.kt @@ -7,19 +7,14 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock import net.horizonsend.ion.server.features.ores.OldOreData import net.horizonsend.ion.server.features.starship.isFlyable -import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.ItemDisplayContainer import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Material.AIR -import org.bukkit.Material.GRAY_CONCRETE import org.bukkit.SoundCategory import org.bukkit.block.Block -import org.bukkit.block.BlockFace import org.bukkit.event.block.BlockBreakEvent import org.bukkit.inventory.ItemStack import org.bukkit.scheduler.BukkitRunnable -import org.bukkit.util.Vector -import org.joml.Vector3f class DecomposeTask( private val entity: DecomposerMultiblock.DecomposerEntity, @@ -31,32 +26,6 @@ class DecomposeTask( private var currentBlock: Block = entity.getBlockRelative(1, 1, 1) - private val displayItem = ItemStack(GRAY_CONCRETE) - - val rightDisplay = ItemDisplayContainer( - entity.world, - 0.25f, - entity.vec3i.toCenterVector(), - entity.structureDirection.rightFace.direction, - displayItem - ).apply { scale = Vector3f(0.25f, 0.25f, 1.0f) } - - val upDisplay = ItemDisplayContainer( - entity.world, - 0.25f, - entity.vec3i.toCenterVector(), - BlockFace.UP.direction, - displayItem - ).apply { scale = Vector3f(0.25f, 0.25f, 1.0f) } - - val forwardDisplay = ItemDisplayContainer( - entity.world, - 0.25f, - entity.vec3i.toCenterVector(), - entity.structureDirection.direction, - displayItem - ).apply { scale = Vector3f(0.25f, 0.25f, 1.0f) } - override fun run() { try { if (breakStrip()) return @@ -73,10 +42,6 @@ class DecomposeTask( override fun cancel() { super.cancel() - rightDisplay.remove() - upDisplay.remove() - forwardDisplay.remove() - entity.userManager.getUserPlayer()?.information("Decomposer broke $totalBlocksBroken blocks.") entity.userManager.clear() entity.currentTask = null @@ -152,7 +117,6 @@ class DecomposeTask( } } - updateDisplays() totalBlocksBroken++ iterationBroken++ } @@ -174,36 +138,6 @@ class DecomposeTask( return success } - private fun updateDisplays() { - val block = currentBlock - val origin = entity.getOrigin() - val right = entity.structureDirection.rightFace - - // + 1 to get one block inside the frame - val currentWidth = (right.modX * (block.x - origin.x)) + (right.modZ * (block.z - origin.z)) + 1 - val currentHeight = block.y - origin.y + 1 - val currentDepth = (entity.structureDirection.modX * (block.x - origin.x)) + (entity.structureDirection.modZ * (block.z - origin.z)) + 1 - - val heightOffset = Vector(0, currentHeight, 0) - val widthOffset = Vector(currentWidth * right.modX, 0, currentWidth * right.modZ) - val depthOffset = Vector(currentWidth * right.modX, currentHeight, currentWidth * right.modZ) - - // Up display comes out of the width defining bar - upDisplay.offset = widthOffset.toVector3f() - upDisplay.scale = Vector3f(0f, 0f, currentDepth.toFloat()) - upDisplay.update() - - // Right display comes out of the vertical bar - rightDisplay.offset = heightOffset.toVector3f() - upDisplay.scale = Vector3f(0f, 0f, currentDepth.toFloat()) - upDisplay.update() - - // Depth display comes from the intersection point of the 2 bars - forwardDisplay.offset = depthOffset.toVector3f() - forwardDisplay.scale = Vector3f(0f, 0f, currentDepth.toFloat()) - forwardDisplay.update() - } - private fun moveForward(): Boolean { val next = getNextBlock(currentBlock) ?: return false currentBlock = next From 303909949577b62c640f7fb71d4a58ea5427acb9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 3 Nov 2024 20:36:29 -0600 Subject: [PATCH 255/500] Add a try catch, fix initialization order, remove old powered multiblock interface --- .../features/custom/items/misc/MultiblockToken.kt | 2 +- .../entity/type/power/PoweredMultiblockEntity.kt | 5 +++-- .../multiblock/type/PowerStoringMultiblock.kt | 5 ----- .../{NewPoweredMultiblock.kt => PoweredMultiblock.kt} | 4 ++-- .../multiblock/type/ammo/AmmoLoaderMultiblock.kt | 4 ++-- .../multiblock/type/ammo/AmmoPressMultiblock.kt | 11 +++++------ .../multiblock/type/ammo/MissileLoaderMultiblock.kt | 8 ++++---- .../type/autocrafter/AutoCrafterMultiblock.kt | 4 ++-- .../multiblock/type/cosmetic/PyrotechnicMachine.kt | 5 ++--- .../type/defense/active/AntiAirCannonMultiblock.kt | 5 ++--- .../type/defense/passive/areashield/AreaShield.kt | 4 ++-- .../multiblock/type/drills/DrillMultiblock.kt | 4 ++-- .../type/farming/harvester/HarvesterMultiblock.kt | 4 ++-- .../type/farming/planter/PlanterMultiblock.kt | 4 ++-- .../multiblock/type/fluid/ElectrolysisMultiblock.kt | 4 ++-- .../multiblock/type/fluid/GasPowerPlantMultiblock.kt | 4 ++-- .../multiblock/type/industry/CentrifugeMultiblock.kt | 4 ++-- .../multiblock/type/industry/CircuitfabMultiblock.kt | 4 ++-- .../multiblock/type/industry/CompressorMultiblock.kt | 4 ++-- .../multiblock/type/industry/FabricatorMultiblock.kt | 4 ++-- .../multiblock/type/industry/GasFurnaceMultiblock.kt | 4 ++-- .../multiblock/type/industry/PlatePressMultiblock.kt | 4 ++-- .../multiblock/type/misc/DecomposerMultiblock.kt | 4 ++-- .../multiblock/type/misc/DisposalMultiblock.kt | 4 ++-- .../multiblock/type/misc/ShipFactoryMultiblock.kt | 5 ++--- .../type/power/charger/ChargerMultiblock.kt | 4 ++-- .../type/power/generator/GeneratorMultiblock.kt | 4 ++-- .../type/power/powerfurnace/PowerFurnaceMultiblock.kt | 4 ++-- .../type/power/storage/PowerBankMultiblock.kt | 4 ++-- .../type/power/storage/PowerCellMultiblock.kt | 4 ++-- .../type/printer/CarbonProcessorMultiblock.kt | 4 ++-- .../multiblock/type/printer/PrinterMultiblock.kt | 4 ++-- .../starship/mininglasers/MiningLaserMultiblock.kt | 4 ++-- .../ion/server/features/transport/old/Wires.kt | 8 +++----- .../server/miscellaneous/registrations/Listeners.kt | 4 ++-- 35 files changed, 74 insertions(+), 84 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PowerStoringMultiblock.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{NewPoweredMultiblock.kt => PoweredMultiblock.kt} (93%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index 81b6cab503..a905c38a1f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -71,7 +71,7 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { return } - PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData) + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData) } itemStack.amount-- } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 56756e106e..a33efb4b93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,15 +1,16 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { - val multiblock: NewPoweredMultiblock<*> val powerStorage: PowerStorage fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { + val multiblock = (this as MultiblockEntity).multiblock as PoweredMultiblock<*> return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PowerStoringMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PowerStoringMultiblock.kt deleted file mode 100644 index 3c810de884..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PowerStoringMultiblock.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type - -interface PowerStoringMultiblock { - val maxPower: Int -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PoweredMultiblock.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PoweredMultiblock.kt index a2c2f027a4..0188d74a7f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/NewPoweredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/PoweredMultiblock.kt @@ -11,7 +11,7 @@ import org.bukkit.block.Sign import org.bukkit.event.EventHandler import org.bukkit.event.player.PlayerInteractEvent -interface NewPoweredMultiblock : EntityMultiblock { +interface PoweredMultiblock : EntityMultiblock { val maxPower: Int fun handleBatteryInput(sign: Sign, entity: PoweredMultiblockEntity, event: PlayerInteractEvent) { @@ -37,7 +37,7 @@ interface NewPoweredMultiblock : EntityMultiblock { fun onPlayerInteract(event: PlayerInteractEvent) { val sign = event.clickedBlock?.state as? Sign ?: return val multiblock = MultiblockAccess.getFast(sign) ?: return - if (multiblock !is NewPoweredMultiblock<*>) return + if (multiblock !is PoweredMultiblock<*>) return val entity = multiblock.getMultiblockEntity(sign) ?: return val item = event.item ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 2ec9d9c79b..8552e2f1bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -10,14 +10,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object AmmoLoaderMultiblock : Multiblock(), NewPoweredMultiblock { +object AmmoLoaderMultiblock : Multiblock(), PoweredMultiblock { override val maxPower = 250_000 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index 5578b25213..440bfa4a4f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -1,12 +1,11 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.attribute.AmmunitionRefillType -import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes -import net.horizonsend.ion.server.features.machine.PowerMachines import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.custom.items.attribute.AmmunitionRefillType +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -20,7 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.Material.matchMaterial @@ -32,7 +31,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext import java.lang.Integer.min -abstract class AmmoPressMultiblock : Multiblock(), NewPoweredMultiblock { +abstract class AmmoPressMultiblock : Multiblock(), PoweredMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index 4153e18e1c..419f4370b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -10,14 +10,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object MissileLoaderMultiblock : Multiblock(), NewPoweredMultiblock { +object MissileLoaderMultiblock : Multiblock(), PoweredMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { @@ -154,10 +154,10 @@ object MissileLoaderMultiblock : Multiblock(), NewPoweredMultiblock { +) : Multiblock(), PoweredMultiblock { override val name = "autocrafter" override val requiredPermission: String? = "ion.multiblock.autocrafter" open val mirrored: Boolean = false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt index 4f187d2fac..a1e572036b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/cosmetic/PyrotechnicMachine.kt @@ -2,10 +2,9 @@ package net.horizonsend.ion.server.features.multiblock.type.cosmetic import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import org.bukkit.Material -abstract class PyrotechnicMachine : Multiblock(), PowerStoringMultiblock { +abstract class PyrotechnicMachine : Multiblock() { override fun MultiblockShape.buildStructure() { z(+0) { y(+0) { @@ -65,7 +64,7 @@ abstract class PyrotechnicMachine : Multiblock(), PowerStoringMultiblock { } } - override val maxPower = 50_000 +// override val maxPower = 50_000 override val name = "pyromachine" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt index ff16fd093e..63a85f8e38 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/active/AntiAirCannonMultiblock.kt @@ -9,7 +9,6 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.features.multiblock.type.defense.active.projectile.AntiAirCannonProjectile import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.RotatingMultiblock import net.horizonsend.ion.server.features.starship.control.movement.PlayerStarshipControl @@ -28,9 +27,9 @@ import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -object AntiAirCannonBaseMultiblock : Multiblock(), PowerStoringMultiblock, InteractableMultiblock { +object AntiAirCannonBaseMultiblock : Multiblock()/*, PowerStoringMultiblock*/, InteractableMultiblock { override val name: String = "antiaircannon" - override val maxPower: Int = 1_000_000 +// override val maxPower: Int = 1_000_000 private val turretPivotPoint = Vec3i(0, 3, -4) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index d904ca9903..f1bdb11ca8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -28,7 +28,7 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext import java.util.concurrent.TimeUnit -abstract class AreaShield(val radius: Int) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { +abstract class AreaShield(val radius: Int) : Multiblock(), PoweredMultiblock, InteractableMultiblock { override fun onTransformSign(player: Player, sign: Sign) { player.success("Area Shield created.") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index aaf08163f8..1a8bd34289 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -23,7 +23,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -53,7 +53,7 @@ import java.util.EnumSet import java.util.UUID import kotlin.math.max -abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { +abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), PoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val radius: Int abstract val coolDown: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 22a3953a9b..f24f995d72 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils @@ -35,7 +35,7 @@ import org.bukkit.block.Sign import org.bukkit.block.data.Ageable import org.bukkit.persistence.PersistentDataAdapterContext -abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { +abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), PoweredMultiblock { override val name: String = "harvester" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index fb5869af33..8ced99e30d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component @@ -34,7 +34,7 @@ import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), NewPoweredMultiblock { +abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), PoweredMultiblock { override val name: String = "planter" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index a7bf66ff80..65859f7e8a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -22,7 +22,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs import net.horizonsend.ion.server.features.starship.movement.StarshipMovement @@ -52,7 +52,7 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext -object ElectrolysisMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { +object ElectrolysisMultiblock : Multiblock(), PoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { override val name: String = "ElectrolysisMultiblock" override val alternativeDetectionNames: Array = arrayOf("Electrolysis") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt index a1e5c4beb2..4ea93f29e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/GasPowerPlantMultiblock.kt @@ -22,7 +22,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -37,7 +37,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext import kotlin.math.roundToInt -object GasPowerPlantMultiblock : Multiblock(), NewPoweredMultiblock { +object GasPowerPlantMultiblock : Multiblock(), PoweredMultiblock { override val maxPower: Int = 500000 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index 88767804ab..a1bffaa0e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -10,14 +10,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object CentrifugeMultiblock : Multiblock(), NewPoweredMultiblock { +object CentrifugeMultiblock : Multiblock(), PoweredMultiblock { override val name = "centrifuge" override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt index 314101a912..e8c9f2a574 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt @@ -10,13 +10,13 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object CircuitfabMultiblock : Multiblock(), NewPoweredMultiblock { +object CircuitfabMultiblock : Multiblock(), PoweredMultiblock { override val name = "circuitfab" override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt index 3ca8a01a3d..52e31ac4dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt @@ -10,14 +10,14 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object CompressorMultiblock : Multiblock(), NewPoweredMultiblock { +object CompressorMultiblock : Multiblock(), PoweredMultiblock { override val maxPower = 300_000 override val name = "compressor" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt index 576b6b38ee..fd6ee58478 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt @@ -11,13 +11,13 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object FabricatorMultiblock : Multiblock(), NewPoweredMultiblock { +object FabricatorMultiblock : Multiblock(), PoweredMultiblock { override val name = "fabricator" override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt index 526fbf25cc..9affa67f08 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/GasFurnaceMultiblock.kt @@ -10,13 +10,13 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object GasFurnaceMultiblock : Multiblock(), NewPoweredMultiblock { +object GasFurnaceMultiblock : Multiblock(), PoweredMultiblock { override val maxPower: Int = 250_000 override val name = "gasfurnace" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt index d1fa0a86ae..3a72bf650d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/PlatePressMultiblock.kt @@ -10,13 +10,13 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object PlatePressMultiblock : Multiblock(), NewPoweredMultiblock { +object PlatePressMultiblock : Multiblock(), PoweredMultiblock { override val maxPower = 300_000 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt index 82c95a8829..12ae972585 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt @@ -21,7 +21,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.listener.misc.ProtectionListener.isRegionDenied import net.horizonsend.ion.server.miscellaneous.utils.CHISELED_TYPES @@ -36,7 +36,7 @@ import org.bukkit.entity.Player import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent -object DecomposerMultiblock : Multiblock(), NewPoweredMultiblock, InteractableMultiblock { +object DecomposerMultiblock : Multiblock(), PoweredMultiblock, InteractableMultiblock { override val maxPower: Int = 75_000 override val name: String = "decomposer" override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt index 61d0cc5da6..95b02e4077 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor @@ -22,7 +22,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import kotlin.math.roundToInt -abstract class AbstractDisposalMultiblock : Multiblock(), NewPoweredMultiblock { +abstract class AbstractDisposalMultiblock : Multiblock(), PoweredMultiblock { override val name = "incinerator" override var signText: Array = arrayOf( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt index ce0c073261..aaa8b3f05b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock import net.horizonsend.ion.server.features.starship.factory.StarshipFactories import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.getFacing @@ -15,7 +14,7 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder -object ShipFactoryMultiblock : Multiblock(), PowerStoringMultiblock, InteractableMultiblock { +object ShipFactoryMultiblock : Multiblock(), InteractableMultiblock { override val name = "shipfactory" override val signText = createSignText( @@ -25,7 +24,7 @@ object ShipFactoryMultiblock : Multiblock(), PowerStoringMultiblock, Interactabl line4 = null ) - override val maxPower: Int = 1_000_000 +// override val maxPower: Int = 1_000_000 override fun onTransformSign(player: Player, sign: Sign) { sign.setLine(2, sign.getLine(1)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index 270be379c6..0aef403f35 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -18,7 +18,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import org.bukkit.Material @@ -30,7 +30,7 @@ import org.bukkit.event.inventory.FurnaceBurnEvent import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext -abstract class ChargerMultiblock(val tierText: String) : Multiblock(), NewPoweredMultiblock, FurnaceMultiblock, DisplayNameMultilblock { +abstract class ChargerMultiblock(val tierText: String) : Multiblock(), PoweredMultiblock, FurnaceMultiblock, DisplayNameMultilblock { protected abstract val tierMaterial: Material protected abstract val powerPerSecond: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 225ae2c068..0b9ad35fde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -17,7 +17,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED @@ -29,7 +29,7 @@ import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory import org.bukkit.persistence.PersistentDataAdapterContext -abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), NewPoweredMultiblock { +abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), PoweredMultiblock { override val name = "generator" abstract val speed: Double diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index c5ceffa9c7..8409664f57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -19,7 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN @@ -38,7 +38,7 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext import java.util.Optional -abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock { +abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), PoweredMultiblock { override val name = "powerfurnace" protected abstract val burnTime: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index 180a492aa9..b4f57e9f40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import org.bukkit.Material @@ -26,7 +26,7 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PowerBankMultiblock(tierText: String) : Multiblock(), NewPoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), PoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val tierMaterial: Material override val name = "powerbank" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 95ee673a8d..88c45bc0c0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import org.bukkit.World @@ -19,7 +19,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.persistence.PersistentDataAdapterContext -object PowerCellMultiblock : Multiblock(), NewPoweredMultiblock, DisplayNameMultilblock { +object PowerCellMultiblock : Multiblock(), PoweredMultiblock, DisplayNameMultilblock { override val name = "powercell" override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt index fc339ffded..df1a07253c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt @@ -14,7 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.isConcretePowder @@ -31,7 +31,7 @@ import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext -object CarbonProcessorMultiblock : Multiblock(), NewPoweredMultiblock { +object CarbonProcessorMultiblock : Multiblock(), PoweredMultiblock { override val maxPower: Int = 30000 override val name = "processor" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt index f242f7e213..70370a8185 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/PrinterMultiblock.kt @@ -14,7 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component @@ -29,7 +29,7 @@ import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PrinterMultiblock : Multiblock(), NewPoweredMultiblock { +abstract class PrinterMultiblock : Multiblock(), PoweredMultiblock { override val name: String = "printer" override val maxPower: Int = 50_000 abstract fun getOutput(product: Material): ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt index 6cee8711ef..fd575b3a33 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblo import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World @@ -18,7 +18,7 @@ import org.bukkit.block.Sign import org.bukkit.inventory.Inventory import org.bukkit.persistence.PersistentDataAdapterContext -abstract class MiningLaserMultiblock : Multiblock(), NewPoweredMultiblock { +abstract class MiningLaserMultiblock : Multiblock(), PoweredMultiblock { override val name = "mininglaser" abstract val range: Double diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt index 4e35aa9c34..bd0684ddec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Wires.kt @@ -5,7 +5,7 @@ import com.google.common.cache.CacheLoader import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.debugHighlightBlock import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield.AreaShield import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -30,8 +30,6 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.ThreadLocalRandom import java.util.concurrent.TimeUnit -import kotlin.collections.component1 -import kotlin.collections.component2 import kotlin.math.min import kotlin.system.measureNanoTime @@ -50,7 +48,7 @@ object Wires : IonServerComponent() { } ) - data class CachedPowerStore(val multiblock: PowerStoringMultiblock, val sign: Sign) + data class CachedPowerStore(val multiblock: Multiblock, val sign: Sign) private val multiblockCache = CacheBuilder.newBuilder() .expireAfterWrite(5, TimeUnit.SECONDS) @@ -294,7 +292,7 @@ object Wires : IonServerComponent() { } val destinationPower = powerSignUpdateCache[destinationSign] - val destinationPowerMax = destinationMultiblock.maxPower + val destinationPowerMax = 0 val destinationFreeSpace = destinationPowerMax - destinationPower val transferLimit = when (destinationMultiblock) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 3411410a94..0ff9dda94c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporter import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.MultiblockEntities -import net.horizonsend.ion.server.features.multiblock.type.NewPoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners import net.horizonsend.ion.server.features.space.encounters.EncounterManager @@ -54,7 +54,7 @@ val listeners: List = listOf( BlockListener, EntityListener, FurnaceListener, - NewPoweredMultiblock.Companion, + PoweredMultiblock.Companion, InventoryListener, BowHitListener, From 84f0f5c220bf6b9bed12a827ed5a958b119c527f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 4 Nov 2024 00:11:04 -0600 Subject: [PATCH 256/500] Add back simple powered multiblock entity but with working initialization order, remove powered entity, move battery listener to its own thing --- .../multiblock/entity/type/RecipeEntity.kt | 27 ++++++-- .../type/power/PoweredMultiblockEntity.kt | 6 +- .../entity/type/power/SimplePoweredEntity.kt | 35 ++++++++++ .../type/ammo/AmmoLoaderMultiblock.kt | 46 ++++--------- .../type/ammo/AmmoPressMultiblock.kt | 7 +- .../type/ammo/MissileLoaderMultiblock.kt | 47 ++++---------- .../type/autocrafter/AutoCrafterMultiblock.kt | 39 +++-------- .../defense/passive/areashield/AreaShield.kt | 58 ++++------------- .../multiblock/type/drills/DrillMultiblock.kt | 43 +++--------- .../farming/harvester/HarvesterMultiblock.kt | 44 +++---------- .../type/farming/planter/PlanterMultiblock.kt | 43 +++--------- .../type/fluid/ElectrolysisMultiblock.kt | 17 ++--- .../type/fluid/GasPowerPlantMultiblock.kt | 19 ++---- .../type/industry/CentrifugeMultiblock.kt | 37 ++--------- .../type/industry/CircuitfabMultiblock.kt | 7 +- .../type/industry/CompressorMultiblock.kt | 46 ++++--------- .../type/industry/FabricatorMultiblock.kt | 30 ++++----- .../type/industry/GasFurnaceMultiblock.kt | 45 ++++--------- .../type/industry/PlatePressMultiblock.kt | 46 ++++--------- .../type/misc/DecomposerMultiblock.kt | 32 ++------- .../type/misc/DisposalMultiblock.kt | 38 ++--------- .../type/power/charger/ChargerMultiblock.kt | 41 +++--------- .../power/generator/GeneratorMultiblock.kt | 20 ++---- .../powerfurnace/PowerFurnaceMultiblock.kt | 6 +- .../type/power/storage/PowerBankMultiblock.kt | 65 +++---------------- .../type/power/storage/PowerCellMultiblock.kt | 57 +++------------- .../type/printer/CarbonProcessorMultiblock.kt | 52 ++++----------- .../type/printer/PrinterMultiblock.kt | 52 ++++----------- .../mininglasers/MiningLaserMultiblock.kt | 40 ++---------- .../misc/BatteryListener.kt} | 38 +++++------ .../miscellaneous/registrations/Listeners.kt | 2 - 31 files changed, 300 insertions(+), 785 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt rename server/src/main/kotlin/net/horizonsend/ion/server/{features/multiblock/type/PoweredMultiblock.kt => listener/misc/BatteryListener.kt} (54%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt index 908a206caf..d87db401c9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt @@ -2,17 +2,34 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity /** * Multiblock which processes multiblock recipes **/ -interface RecipeEntity : ProgressMultiblock { - var currentRecipe: MultiblockRecipe<*> +interface RecipeEntity : ProgressMultiblock, SyncTickingMultiblockEntity { + fun T.getRecipe(): MultiblockRecipe? { + return MultiblockRecipes.getRecipe(this) + } + + override fun tick() { + executeRecipes() + } + + fun executeRecipes() { + this as MultiblockEntity + val recipe = this.getRecipe() + + if (recipe == null) { + tickingManager.sleep(500) + return + } - fun fetchInventories() + if (recipe.canExecute(this)) return - fun getRecipe(): MultiblockRecipe<*>? { - return MultiblockRecipes.getRecipe(this as MultiblockEntity) + val context = RecipeExecutionContext(recipe, this) + context.execute() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index a33efb4b93..98e26bcbf0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,17 +1,15 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { val powerStorage: PowerStorage + val maxPower: Int fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { - val multiblock = (this as MultiblockEntity).multiblock as PoweredMultiblock<*> - return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), multiblock.maxPower) + return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), maxPower) } fun savePowerData(store: PersistentMultiblockData) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt new file mode 100644 index 0000000000..11c13f975f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -0,0 +1,35 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.power + +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.persistence.PersistentDataAdapterContext + +abstract class SimplePoweredEntity( + data: PersistentMultiblockData, + multiblock: Multiblock, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, +) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { + override val powerStorage: PowerStorage = this.loadStoredPower(data) + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + savePowerData(store) + } + + protected fun standardPowerDisplay(entity: SimplePoweredEntity): TextDisplayHandler = DisplayHandlers.newMultiblockSignOverlay( + entity, + PowerEntityDisplay(entity, +0.0, +0.0, +0.0, 0.5f) + ).register() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 8552e2f1bf..77677b6cdf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -1,25 +1,22 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object AmmoLoaderMultiblock : Multiblock(), PoweredMultiblock { - override val maxPower = 250_000 - +object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -151,34 +148,15 @@ object AmmoLoaderMultiblock : Multiblock(), PoweredMultiblock { +abstract class AmmoPressMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { @@ -141,6 +141,8 @@ abstract class AmmoPressMultiblock : Multiblock(), PoweredMultiblock { - +object MissileLoaderMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -141,8 +139,6 @@ object MissileLoaderMultiblock : Multiblock(), PoweredMultiblock { +) : Multiblock(), EntityMultiblock { override val name = "autocrafter" override val requiredPermission: String? = "ion.multiblock.autocrafter" open val mirrored: Boolean = false + abstract val maxPower: Int + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -139,22 +139,17 @@ abstract class AutoCrafterMultiblock( z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, StatusMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity { + override val maxPower: Int = multiblock.maxPower override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - private fun getInput(): Inventory? = getInventory(-2, 0, 1) private fun getRecipeHolder(): Inventory? = getInventory(0, 0, 1) private fun getOutput(): Inventory? = getInventory(+2, 0, 1) @@ -258,22 +253,6 @@ abstract class AutoCrafterMultiblock( } } - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) multiblock.signText.withIndex().forEach { sign.front().line(it.index, it.value.orEmpty()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index f1bdb11ca8..58205af929 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -2,18 +2,14 @@ package net.horizonsend.ion.server.features.multiblock.type.defense.passive.area import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -25,10 +21,9 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataAdapterContext import java.util.concurrent.TimeUnit -abstract class AreaShield(val radius: Int) : Multiblock(), PoweredMultiblock, InteractableMultiblock { +abstract class AreaShield(val radius: Int) : Multiblock(), EntityMultiblock, InteractableMultiblock { override fun onTransformSign(player: Player, sign: Sign) { player.success("Area Shield created.") } @@ -65,10 +60,7 @@ abstract class AreaShield(val radius: Int) : Multiblock(), PoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { +abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val radius: Int - abstract val coolDown: Int - abstract val mirrored: Boolean + abstract val maxPower: Int override val name = "drill" @@ -136,10 +131,11 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection), UserManagedMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity { + override val maxPower: Int = multiblock.maxPower override val tickingManager: TickingManager = TickingManager(interval = 5) override val userManager: UserManager = UserManager(data, persistent = true) + override val displayHandler: TextDisplayHandler = standardPowerDisplay(this) override fun tick() { val player = userManager.getUserPlayer() ?: return disable() @@ -240,31 +236,10 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - userManager.saveUserData(store) + super.storeAdditionalData(store, adapterContext) savePowerData(store) } - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index f24f995d72..6fa54d0b0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -5,19 +5,17 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -33,9 +31,8 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.Ageable -import org.bukkit.persistence.PersistentDataAdapterContext -abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), PoweredMultiblock { +abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock { override val name: String = "harvester" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), @@ -47,6 +44,8 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I val powerPerCrop: Int = 10 abstract val regionDepth: Int + abstract val maxPower: Int + override fun MultiblockShape.buildStructure() { z(0) { y(-1) { @@ -119,22 +118,17 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblockEntity { + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusTickedMultiblockEntity { + override val maxPower: Int = multiblock.maxPower override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickingManager = TickingManager(interval = 20) - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - override fun tick() { val inventory = getInventory(right = 0, up = 0, forward = 2) ?: return tickingManager.sleep(1000) var broken = 0 @@ -184,26 +178,6 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I setStatus(text("Working", GREEN)) } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 8ced99e30d..1c780ea916 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -5,19 +5,18 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE @@ -32,9 +31,8 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory -import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), PoweredMultiblock { +abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock { override val name: String = "planter" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), @@ -46,6 +44,8 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int abstract val regionDepth: Int private val powerPerCrop: Int = 10 + abstract val maxPower: Int + override fun MultiblockShape.buildStructure() { z(0) { y(-1) { @@ -110,22 +110,17 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection), PoweredMultiblockEntity, SyncTickingMultiblockEntity, LegacyMultiblockEntity, StatusTickedMultiblockEntity { + override val maxPower = multiblock.maxPower override val tickingManager: TickingManager = TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) ).register() - private fun sleepWithStatus(status: Component, sleepTicks: Int) { - setStatus(status) - tickingManager.sleep(sleepTicks) - } - override fun tick() { var planted = 0 val initialPower = powerStorage.getPower() @@ -163,26 +158,6 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int setStatus(text("Working", GREEN)) } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 65859f7e8a..00e00f23d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -21,8 +21,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedM import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs import net.horizonsend.ion.server.features.starship.movement.StarshipMovement @@ -52,7 +52,7 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext -object ElectrolysisMultiblock : Multiblock(), PoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { +object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { override val name: String = "ElectrolysisMultiblock" override val alternativeDetectionNames: Array = arrayOf("Electrolysis") @@ -179,8 +179,6 @@ object ElectrolysisMultiblock : Multiblock(), PoweredMultiblock { - - override val maxPower: Int = 500000 - +object GasPowerPlantMultiblock : Multiblock(), EntityMultiblock { override val name: String = "gaspowerplant" override val signText: Array = arrayOf( @@ -180,7 +174,8 @@ object GasPowerPlantMultiblock : Multiblock(), PoweredMultiblock { +object CentrifugeMultiblock : Multiblock(), EntityMultiblock { override val name = "centrifuge" override val signText = createSignText( @@ -27,8 +23,6 @@ object CentrifugeMultiblock : Multiblock(), PoweredMultiblock { +object CircuitfabMultiblock : Multiblock(), EntityMultiblock { override val name = "circuitfab" override val signText = createSignText( @@ -26,8 +26,6 @@ object CircuitfabMultiblock : Multiblock(), PoweredMultiblock { - override val maxPower = 300_000 - +object CompressorMultiblock : Multiblock(), EntityMultiblock { override val name = "compressor" override val signText = createSignText( @@ -127,34 +124,15 @@ object CompressorMultiblock : Multiblock(), PoweredMultiblock { +object FabricatorMultiblock : Multiblock(), EntityMultiblock { override val name = "fabricator" override val signText = createSignText( @@ -27,8 +26,6 @@ object FabricatorMultiblock : Multiblock(), PoweredMultiblock { - override val maxPower: Int = 250_000 +object GasFurnaceMultiblock : Multiblock(), EntityMultiblock { override val name = "gasfurnace" override val signText = createSignText( @@ -89,34 +87,15 @@ object GasFurnaceMultiblock : Multiblock(), PoweredMultiblock { - override val maxPower = 300_000 - +object PlatePressMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -126,34 +123,15 @@ object PlatePressMultiblock : Multiblock(), PoweredMultiblock, InteractableMultiblock { - override val maxPower: Int = 75_000 +object DecomposerMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { override val name: String = "decomposer" override val signText = createSignText( "&cDecomposer", @@ -74,13 +70,13 @@ object DecomposerMultiblock : Multiblock(), PoweredMultiblock { +abstract class AbstractDisposalMultiblock : Multiblock(), EntityMultiblock { override val name = "incinerator" override var signText: Array = arrayOf( @@ -32,8 +29,6 @@ abstract class AbstractDisposalMultiblock : Multiblock(), PoweredMultiblock, FurnaceMultiblock, DisplayNameMultilblock { +abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMultiblock, FurnaceMultiblock, DisplayNameMultilblock { protected abstract val tierMaterial: Material protected abstract val powerPerSecond: Int override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), Component.text(" Item Charger")) + abstract val maxPower: Int + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -108,13 +106,10 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), PoweredMu z: Int, world: World, signDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, signDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { + override val maxPower: Int = multiblock.maxPower override val powerStorage: PowerStorage = loadStoredPower(data) - - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() + override val displayHandler = standardPowerDisplay(this) fun handleCharging(event: FurnaceBurnEvent, furnace: Furnace) { val availablePower = powerStorage.getPower() @@ -166,26 +161,6 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), PoweredMu event.burnTime = 20 } - override fun onLoad() { - displayHandler.update() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 0b9ad35fde..c2cbe433b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -5,19 +5,16 @@ import net.horizonsend.ion.server.features.client.display.modular.display.PowerE import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED @@ -27,12 +24,13 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory -import org.bukkit.persistence.PersistentDataAdapterContext -abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), PoweredMultiblock { +abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), EntityMultiblock { override val name = "generator" abstract val speed: Double + abstract val maxPower: Int + override val signText = createSignText( line1 = "&2Power", line2 = "&8Generator", @@ -69,8 +67,8 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, PoweredMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity, DisplayMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, LegacyMultiblockEntity { + override val maxPower: Int = multiblock.maxPower override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() @@ -105,10 +103,6 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M powerStorage.addPower(fuel.power) } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index 8409664f57..4a3a4f6cb6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -19,7 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN @@ -38,9 +38,10 @@ import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext import java.util.Optional -abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), PoweredMultiblock { +abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMultiblock { override val name = "powerfurnace" + abstract val maxPower: Int protected abstract val burnTime: Int protected abstract val tierMaterial: Material @@ -95,6 +96,7 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), PoweredM structureDirection: BlockFace, ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, PoweredMultiblockEntity, LegacyMultiblockEntity, DisplayMultiblockEntity { + override val maxPower: Int = multiblock.maxPower override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index b4f57e9f40..ddb1608963 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -3,20 +3,16 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.legacyAmpersand import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers.newMultiblockSignOverlay -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.World @@ -24,9 +20,9 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataAdapterContext -abstract class PowerBankMultiblock(tierText: String) : Multiblock(), PoweredMultiblock, InteractableMultiblock, DisplayNameMultilblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { + abstract val maxPower: Int abstract val tierMaterial: Material override val name = "powerbank" @@ -96,25 +92,8 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), PoweredMult player.information("b: ${b.powerStorage.getPower()}") } - override fun createEntity( - manager: MultiblockManager, - data: PersistentMultiblockData, - world: World, - x: Int, - y: Int, - z: Int, - structureDirection: BlockFace - ): PowerBankEntity { - return PowerBankEntity( - data, - manager, - this, - x, - y, - z, - world, - structureDirection - ) + override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PowerBankEntity { + return PowerBankEntity(data, manager, this, x, y, z, world, structureDirection) } class PowerBankEntity( @@ -125,34 +104,10 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), PoweredMult y: Int, z: Int, world: World, - structureDirection: BlockFace - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, LegacyMultiblockEntity { - override val powerStorage: PowerStorage = loadStoredPower(data) - - private val displayHandler = newMultiblockSignOverlay( - this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.5f) - ).register() - - override fun onLoad() { - displayHandler.update() - } - - override fun onUnload() { - displayHandler.remove() - } - - override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } + structureFace: BlockFace + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureFace), LegacyMultiblockEntity, PoweredMultiblockEntity { + override val maxPower = multiblock.maxPower + override val displayHandler = standardPowerDisplay(this) override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 88c45bc0c0..49aa07133b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -1,25 +1,20 @@ package net.horizonsend.ion.server.features.multiblock.type.power.storage -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.kyori.adventure.text.Component import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign -import org.bukkit.persistence.PersistentDataAdapterContext -object PowerCellMultiblock : Multiblock(), PoweredMultiblock, DisplayNameMultilblock { +object PowerCellMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "powercell" override val signText = createSignText( @@ -31,8 +26,6 @@ object PowerCellMultiblock : Multiblock(), PoweredMultiblock { - override val maxPower: Int = 30000 +object CarbonProcessorMultiblock : Multiblock(), EntityMultiblock { override val name = "processor" override val signText = createSignText( @@ -97,22 +93,20 @@ object CarbonProcessorMultiblock : Multiblock(), PoweredMultiblock { +abstract class PrinterMultiblock : Multiblock(), EntityMultiblock { override val name: String = "printer" - override val maxPower: Int = 50_000 abstract fun getOutput(product: Material): ItemStack abstract val mirrored: Boolean @@ -142,21 +137,20 @@ abstract class PrinterMultiblock : Multiblock(), PoweredMultiblock { +abstract class MiningLaserMultiblock : Multiblock(), EntityMultiblock { override val name = "mininglaser" abstract val range: Double @@ -31,6 +26,7 @@ abstract class MiningLaserMultiblock : Multiblock(), PoweredMultiblock : EntityMultiblock { - val maxPower: Int +object BatteryListener : SLEventListener() { + @EventHandler + fun onPlayerInteract(event: PlayerInteractEvent) { + val sign = event.clickedBlock?.state as? Sign ?: return + val multiblock = MultiblockAccess.getFast(sign) ?: return + if (multiblock !is EntityMultiblock<*>) return - fun handleBatteryInput(sign: Sign, entity: PoweredMultiblockEntity, event: PlayerInteractEvent) { + val entity = multiblock.getMultiblockEntity(sign) ?: return + if (entity !is PoweredMultiblockEntity) return + + val item = event.item ?: return + if (CustomItems[item] !is CustomItems.BatteryItem) return + + handleBatteryInput(entity, event) + } + + private fun handleBatteryInput(entity: PoweredMultiblockEntity, event: PlayerInteractEvent) { val item = event.item ?: return val power = getPower(item) @@ -31,19 +44,4 @@ interface PoweredMultiblock : EntityMultiblock { setPower(item, power - powerToTransfer / item.amount) entity.powerStorage.addPower(powerToTransfer) } - - companion object : SLEventListener() { - @EventHandler - fun onPlayerInteract(event: PlayerInteractEvent) { - val sign = event.clickedBlock?.state as? Sign ?: return - val multiblock = MultiblockAccess.getFast(sign) ?: return - if (multiblock !is PoweredMultiblock<*>) return - val entity = multiblock.getMultiblockEntity(sign) ?: return - - val item = event.item ?: return - if (CustomItems[item] !is CustomItems.BatteryItem) return - - multiblock.handleBatteryInput(sign, entity as PoweredMultiblockEntity, event) - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 0ff9dda94c..a964fa9d14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporter import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.MultiblockEntities -import net.horizonsend.ion.server.features.multiblock.type.PoweredMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam import net.horizonsend.ion.server.features.progression.achievements.AchievementListeners import net.horizonsend.ion.server.features.space.encounters.EncounterManager @@ -54,7 +53,6 @@ val listeners: List = listOf( BlockListener, EntityListener, FurnaceListener, - PoweredMultiblock.Companion, InventoryListener, BowHitListener, From 7e30461c07ae12edaa2f10b6e203342656bc7890 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 4 Nov 2024 00:15:00 -0600 Subject: [PATCH 257/500] unregister ionworlds after components --- .../src/main/kotlin/net/horizonsend/ion/server/IonServer.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt index 1b91a532d0..7ac5061840 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt @@ -145,8 +145,6 @@ object IonServer : JavaPlugin() { } override fun onDisable() { - IonWorld.unregisterAll() - SLCommand.ASYNC_COMMAND_THREAD.shutdown() for (component in components.asReversed()) try { @@ -156,6 +154,8 @@ object IonServer : JavaPlugin() { slF4JLogger.error("There was an error shutting down ${component.javaClass.simpleName}! ${e.message}") e.printStackTrace() } + + IonWorld.unregisterAll() } override fun getDefaultBiomeProvider(worldName: String, id: String?): BiomeProvider { From 63e28fcbfb4c047fbbb2cf99a4fb404877c5d24e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 4 Nov 2024 10:05:23 -0600 Subject: [PATCH 258/500] Fix initialization order problems --- .../modular/display/PowerEntityDisplay.kt | 4 +-- .../entity/type/power/PowerStorage.kt | 1 + .../entity/type/power/SimplePoweredEntity.kt | 5 ++- .../type/ammo/AmmoLoaderMultiblock.kt | 3 +- .../type/ammo/AmmoPressMultiblock.kt | 13 ++------ .../type/ammo/MissileLoaderMultiblock.kt | 3 +- .../type/autocrafter/AutoCrafterMultiblock.kt | 3 +- .../defense/passive/areashield/AreaShield.kt | 3 +- .../multiblock/type/drills/DrillMultiblock.kt | 9 +----- .../farming/harvester/HarvesterMultiblock.kt | 3 +- .../type/farming/planter/PlanterMultiblock.kt | 3 +- .../type/fluid/GasPowerPlantMultiblock.kt | 5 +-- .../type/industry/CentrifugeMultiblock.kt | 3 +- .../type/industry/CircuitfabMultiblock.kt | 32 ++----------------- .../type/industry/CompressorMultiblock.kt | 3 +- .../type/industry/FabricatorMultiblock.kt | 3 +- .../type/industry/GasFurnaceMultiblock.kt | 3 +- .../type/industry/PlatePressMultiblock.kt | 3 +- .../type/misc/DecomposerMultiblock.kt | 6 ++-- .../type/misc/DisposalMultiblock.kt | 3 +- .../type/power/charger/ChargerMultiblock.kt | 5 +-- .../power/generator/GeneratorMultiblock.kt | 3 +- .../powerfurnace/PowerFurnaceMultiblock.kt | 15 ++------- .../type/power/storage/PowerBankMultiblock.kt | 3 +- .../type/power/storage/PowerCellMultiblock.kt | 3 +- .../type/printer/CarbonProcessorMultiblock.kt | 3 +- .../type/printer/PrinterMultiblock.kt | 3 +- .../mininglasers/MiningLaserMultiblock.kt | 6 +--- 28 files changed, 38 insertions(+), 114 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt index edcf0b3915..b6857501d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt @@ -22,11 +22,11 @@ class PowerEntityDisplay( } override fun register() { -// multiblockEntity.storage.registerUpdateHandler(updateHandler) + multiblockEntity.powerStorage.registerUpdateHandler(updateHandler) } override fun deRegister() { -// multiblockEntity.storage.removeUpdateHandler(updateHandler) + multiblockEntity.powerStorage.removeUpdateHandler(updateHandler) } override fun getText(): Component { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index 158ccee50c..bb4c5e8fde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -13,6 +13,7 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit fun isFull() = getPower() >= capacity fun setPower(amount: Int) { + Throwable().printStackTrace() synchronized(mutex) { val correctedPower = amount.coerceIn(0, capacity) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index 11c13f975f..828e5c0192 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -8,9 +8,11 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType abstract class SimplePoweredEntity( data: PersistentMultiblockData, @@ -21,8 +23,9 @@ abstract class SimplePoweredEntity( z: Int, world: World, structureDirection: BlockFace, + final override val maxPower: Int ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { - override val powerStorage: PowerStorage = this.loadStoredPower(data) + final override val powerStorage: PowerStorage = PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), maxPower) override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 77677b6cdf..2e9792e463 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -149,8 +149,7 @@ object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock { @@ -152,10 +149,8 @@ abstract class AmmoPressMultiblock : Multiblock(), EntityMultiblock { @@ -94,10 +92,8 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu z: Int, world: World, structureDirection: BlockFace, - ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, PoweredMultiblockEntity, LegacyMultiblockEntity, + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection, multiblock.maxPower), SyncTickingMultiblockEntity, StatusTickedMultiblockEntity, PoweredMultiblockEntity, LegacyMultiblockEntity, DisplayMultiblockEntity { - override val maxPower: Int = multiblock.maxPower - override val powerStorage: PowerStorage = loadStoredPower(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(interval = 20) override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() @@ -136,10 +132,6 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu furnace.update() } - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - savePowerData(store) - } - override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } @@ -156,10 +148,7 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu MinecraftServer.getServer().recipeManager .getRecipeFor(RecipeType.SMELTING, furnaceTile, level) .map { - println("Recipe holder: $it") - println("Recipe: ${it.value}") val b = it.value.assemble(furnaceTile, level.registryAccess()) - println("B: $b") CraftItemStack.asBukkitCopy(b) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index ddb1608963..4e1fb1ed5a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -105,8 +105,7 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMulti z: Int, world: World, structureFace: BlockFace - ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureFace), LegacyMultiblockEntity, PoweredMultiblockEntity { - override val maxPower = multiblock.maxPower + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureFace, multiblock.maxPower), LegacyMultiblockEntity, PoweredMultiblockEntity { override val displayHandler = standardPowerDisplay(this) override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 49aa07133b..01c34410fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -56,8 +56,7 @@ object PowerCellMultiblock : Multiblock(), EntityMultiblock Date: Mon, 4 Nov 2024 12:10:34 -0600 Subject: [PATCH 259/500] missed a couple more, data saving improvements --- .../entity/type/power/PowerStorage.kt | 1 - .../entity/type/power/SimplePoweredEntity.kt | 7 +++++- .../manager/ChunkMultiblockManager.kt | 24 ++++++++----------- .../type/fluid/ElectrolysisMultiblock.kt | 10 +------- .../type/misc/DecomposerMultiblock.kt | 6 +++++ .../node/manager/ChunkTransportManager.kt | 3 --- .../manager/holders/ChunkNetworkHolder.kt | 17 +++++-------- .../node/manager/holders/NetworkHolder.kt | 2 -- .../node/manager/holders/ShipNetworkHolder.kt | 4 ---- .../ion/server/features/world/IonWorld.kt | 9 +++---- .../features/world/chunk/ChunkRegion.kt | 9 ------- .../server/features/world/chunk/IonChunk.kt | 2 +- 12 files changed, 35 insertions(+), 59 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index bb4c5e8fde..158ccee50c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -13,7 +13,6 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit fun isFull() = getPower() >= capacity fun setPower(amount: Int) { - Throwable().printStackTrace() synchronized(mutex) { val correctedPower = amount.coerceIn(0, capacity) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index 828e5c0192..32b15968b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -25,7 +25,12 @@ abstract class SimplePoweredEntity( structureDirection: BlockFace, final override val maxPower: Int ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { - final override val powerStorage: PowerStorage = PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), maxPower) + @Suppress("LeakingThis") // Only a reference is needed, max power is provided in the constructor + final override val powerStorage: PowerStorage = PowerStorage( + this, + data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), + maxPower + ) override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { savePowerData(store) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 1f16b5a936..6e534da1ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -1,7 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.manager -import kotlinx.coroutines.launch -import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -15,7 +13,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.World import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER_ARRAY import org.slf4j.Logger class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManager(log) { @@ -29,6 +27,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag } private var lastSaved = System.currentTimeMillis() + override fun getSignUnsavedTime(): Long { return System.currentTimeMillis() - lastSaved } @@ -53,17 +52,13 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag /** * Save the multiblock data back into the chunk **/ - private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) = MultiblockAccess.multiblockCoroutineScope.launch { - val old = chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) - old?.let { - chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY, it) - } + private fun saveMultiblocks(adapterContext: PersistentDataAdapterContext) { + val previous = chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) + if (previous != null) chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES_OLD, TAG_CONTAINER_ARRAY, previous) - val array = multiblockEntities.map { (_, entity) -> - entity.serialize(adapterContext, entity.store()) - }.toTypedArray() + val array = multiblockEntities.values.map { it.serialize(adapterContext, it.store()) }.toTypedArray() - chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY, array) + chunk.inner.persistentDataContainer.set(STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY, array) } /** @@ -71,7 +66,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag **/ private fun loadMultiblocks() { val serialized = try { - chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return + chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES, TAG_CONTAINER_ARRAY) ?: return } catch (e: IllegalArgumentException) { log.warn("Could not load chunks multiblocks for $chunk") if (e.message == "The found tag instance (NBTTagList) cannot store List") { @@ -83,7 +78,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag arrayOf() } catch (e: Throwable) { // Try to load backup - chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES_OLD, PersistentDataType.TAG_CONTAINER_ARRAY) ?: return + chunk.inner.persistentDataContainer.get(STORED_MULTIBLOCK_ENTITIES_OLD, TAG_CONTAINER_ARRAY) ?: return } catch (e: Throwable) { // Give up return @@ -104,6 +99,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag fun onUnload() { multiblockEntities.values.forEach { it.onUnload() + if (it is DisplayMultiblockEntity) it.displayHandler.remove() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 00e00f23d2..5e9f4e2888 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -180,15 +180,7 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { override val name: String = "decomposer" @@ -132,6 +133,11 @@ object DecomposerMultiblock : Multiblock(), EntityMultiblock> private constructor (val manager: Ch this.network = network(this) } - override val scope: CoroutineScope = manager.scope - override fun getWorld(): World = manager.chunk.world override fun getGlobalNode(key: BlockKey): TransportNode? { @@ -70,13 +65,13 @@ class ChunkNetworkHolder> private constructor (val manager: Ch // Load data sync val good = loadData() - manager.scope.launch { + Tasks.async { val adapterContext = chunkPDC.adapterContext // Handle cases of data corruption if (!good) { network.clearData() - collectAllNodes().join() + collectAllNodes() // Save rebuilt data save(adapterContext) @@ -151,11 +146,11 @@ class ChunkNetworkHolder> private constructor (val manager: Ch /** * Build node data from an unregistered state **/ - private fun collectAllNodes(): Job = manager.scope.launch { + private fun collectAllNodes() { // Parallel collect the nodes of each section manager.chunk.sections.map { (y, _) -> - launch { collectSectionNodes(y) } - }.joinAll() + collectSectionNodes(y) + } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 328d59f4b5..870067e8ee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders -import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager @@ -9,7 +8,6 @@ import org.bukkit.World interface NetworkHolder > { val network: T - val scope: CoroutineScope fun getWorld(): World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index 8763e30992..c2d9942bc2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -1,11 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders -import kotlinx.coroutines.CoroutineScope import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager -import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World import kotlin.properties.Delegates @@ -17,8 +15,6 @@ class ShipNetworkHolder>(val manager: ShipTransportManager) : this.network = network(this) } - override val scope: CoroutineScope = ChunkRegion.scope - override fun getWorld(): World = manager.starship.world override fun handleLoad() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 0f14d314c3..97ed76e279 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -14,9 +14,8 @@ import net.horizonsend.ion.server.features.world.configuration.DefaultWorldConfi import net.horizonsend.ion.server.features.world.data.DataFixers import net.horizonsend.ion.server.features.world.environment.Environment import net.horizonsend.ion.server.features.world.environment.mobs.CustomMobSpawner -import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FORBIDDEN_BLOCKS import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.DATA_VERSION +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FORBIDDEN_BLOCKS import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.mainThreadCheck import org.bukkit.Chunk @@ -27,8 +26,8 @@ import org.bukkit.event.world.WorldInitEvent import org.bukkit.event.world.WorldSaveEvent import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.persistence.PersistentDataType.INTEGER -import java.util.concurrent.ConcurrentHashMap import org.bukkit.persistence.PersistentDataType.LONG_ARRAY +import java.util.concurrent.ConcurrentHashMap import kotlin.DeprecationLevel.ERROR class IonWorld private constructor( @@ -207,7 +206,9 @@ class IonWorld private constructor( } override fun onDisable() { - for (world in ionWorlds.values) saveAllChunks(world) + for (world in ionWorlds.values) { + saveAllChunks(world) + } } private fun saveAllChunks(world: IonWorld) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt index d62a5c4ca1..3ac091e63a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt @@ -1,16 +1,10 @@ package net.horizonsend.ion.server.features.world.chunk -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.asCoroutineDispatcher -import kotlinx.coroutines.launch import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Tasks import org.bukkit.Chunk import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.Executors class ChunkRegion(val world: IonWorld) { val chunks = ConcurrentHashMap() @@ -28,10 +22,7 @@ class ChunkRegion(val world: IonWorld) { world.chunkRegions.remove(this) } - fun launch(block: suspend CoroutineScope.() -> Unit) = scope.launch { block.invoke(this) } - companion object { - val scope = CoroutineScope(Executors.newCachedThreadPool(Tasks.namedThreadFactory("chunk-async-worker")).asCoroutineDispatcher() + SupervisorJob()) const val MAX_SIZE: Int = 50 fun loadChunk(chunk: Chunk) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 137c012e27..e3bdd178ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -146,7 +146,7 @@ class IonChunk( private fun unregisterChunk(chunk: Chunk) { val ionWorld = chunk.world.ion - val removed = ionWorld.removeChunk(chunk) ?: return + val removed = ionWorld.removeChunk(chunk) ?: return log.warn("Removed unregistered IonChunk!") removed.onUnload() ChunkRegion.unloadChunk(removed) From 08c70558554dbb7a158af5286ffe129c437866bf Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 7 Nov 2024 11:42:32 -0600 Subject: [PATCH 260/500] half implemented replacement recipe system --- .../crafting/recipe/take2/IndustryRecipe.kt | 4 ++ .../recipe/take2/LegacyIndustryRecipe.kt | 51 +++++++++++++++++++ .../crafting/recipe/take2/NewRecipe.kt | 22 ++++++++ .../recipe/take2/ingredient/ItemIngredient.kt | 14 +++++ .../ingredient/MultiblockRecipeIngredient.kt | 8 +++ .../take2/ingredient/PowerIngredient.kt | 14 +++++ .../take2/ingredient/ResourceIngredient.kt | 3 ++ .../recipe/take2/result/FluidResult.kt | 5 ++ .../recipe/take2/result/ItemResult.kt | 7 +++ .../take2/result/MultiblockRecipeResult.kt | 5 ++ 10 files changed, 133 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt new file mode 100644 index 0000000000..298939da27 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt @@ -0,0 +1,4 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2 + +class IndustryRecipe { +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt new file mode 100644 index 0000000000..066b7400e0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt @@ -0,0 +1,51 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2 + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient.MultiblockRecipeIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient.ResourceIngredient +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result.FluidResult +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result.MultiblockRecipeResult +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import org.bukkit.inventory.FurnaceInventory +import kotlin.reflect.KClass + +class LegacyIndustryRecipe( + entity: KClass, + private val result: MultiblockRecipeResult, + private val smelting: MultiblockRecipeIngredient?, + private val fuel: MultiblockRecipeIngredient?, + private vararg val resources: ResourceIngredient, +) : NewRecipe(entity) { + + private fun getFurnace(context: ExecutionContext): FurnaceInventory { + return context.entity.getInventory(0, 0, 0) as? FurnaceInventory ?: throw IllegalStateException("Multiblock integrity should be ensured before execution") + } + + override fun checkResourcesAvailable(context: ExecutionContext): Boolean { + if (smelting?.check(context) == false) return false + if (fuel?.check(context) == false) return false + return resources.all { it.check(context) } + } + + override fun checkSpaceAvailable(context: ExecutionContext): Boolean { + val furnace = getFurnace(context) + + return when (result) { + is ItemResult -> { + val resultSlot = furnace.result ?: return true + val resultItem = result.assemble() + if (resultSlot.isSimilar(resultItem)) return false + if (resultItem.amount + resultSlot.amount > resultSlot.maxStackSize) return false + true + } + is FluidResult -> context.entity is FluidStoringEntity && context.entity.canStore(result.fluid, result.amount) + else -> false + } + } + + override fun execute(context: ExecutionContext) { + val furnace = getFurnace(context) + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt new file mode 100644 index 0000000000..241545488a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt @@ -0,0 +1,22 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2 + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.minecraft.commands.execution.ExecutionContext +import kotlin.reflect.KClass + +abstract class NewRecipe(val multiblockEntity: KClass) { + abstract fun checkSpaceAvailable(context: ExecutionContext): Boolean + + abstract fun checkResourcesAvailable(context: ExecutionContext): Boolean + + fun checkExecution(context: ExecutionContext): Boolean { + if (!checkResourcesAvailable(context)) return false + if (!checkSpaceAvailable(context)) return false + //TODO + return true + } + + abstract fun execute(context: ExecutionContext) + + class ExecutionContext(val entity: MultiblockEntity) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt new file mode 100644 index 0000000000..75c8b48c7b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.NewRecipe +import org.bukkit.inventory.ItemStack + +class ItemIngredient(private val item: ItemStack) : MultiblockRecipeIngredient() { + override fun check(context: NewRecipe.ExecutionContext): Boolean { + return true + } + + override fun consume(context: NewRecipe.ExecutionContext) { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt new file mode 100644 index 0000000000..0b9d9324f1 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.NewRecipe + +abstract class MultiblockRecipeIngredient { + abstract fun consume(context: NewRecipe.ExecutionContext) + abstract fun check(context: NewRecipe.ExecutionContext): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt new file mode 100644 index 0000000000..cea15e5935 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient + +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.NewRecipe +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity + +class PowerIngredient(private val amount: Int) : ResourceIngredient() { + override fun check(context: NewRecipe.ExecutionContext): Boolean { + return context.entity is PoweredMultiblockEntity && context.entity.powerStorage.canRemovePower(amount) + } + + override fun consume(context: NewRecipe.ExecutionContext) { + (context.entity as PoweredMultiblockEntity).powerStorage.removePower(amount) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt new file mode 100644 index 0000000000..2eec28b02a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt @@ -0,0 +1,3 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient + +abstract class ResourceIngredient : MultiblockRecipeIngredient() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt new file mode 100644 index 0000000000..cd884584f4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result + +import net.horizonsend.ion.server.features.transport.fluids.PipedFluid + +class FluidResult(val fluid: PipedFluid, val amount: Int) : MultiblockRecipeResult() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt new file mode 100644 index 0000000000..42a51213a2 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result + +import org.bukkit.inventory.ItemStack + +class ItemResult(private val item: ItemStack) : MultiblockRecipeResult() { + fun assemble(): ItemStack = item.clone() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt new file mode 100644 index 0000000000..1d11bc1e95 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result + +abstract class MultiblockRecipeResult { +// abstract fun assemble() +} From 4654ebedecec43572c440ea7cddf8c1836bae3e1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 8 Nov 2024 11:34:57 -0600 Subject: [PATCH 261/500] start of node replacement --- .../features/transport/cache/CachedNode.kt | 14 +++++ .../transport/cache/PowerTransportCache.kt | 34 +++++++++++++ .../transport/cache/TransportCache.kt | 51 +++++++++++++++++++ .../transport/cache/state/CacheState.kt | 8 +++ 4 files changed, 107 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt new file mode 100644 index 0000000000..308bf33351 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.transport.cache + +import org.bukkit.Material +import org.bukkit.block.BlockFace + +interface CachedNode { + // The backing material(s) of this node type + fun isMatchingMaterial(material: Material): Boolean + + /** + * Gets the directions that should be checked for the next nodes + **/ + fun getNextNodes(inputDirection: BlockFace): Set +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt new file mode 100644 index 0000000000..ef788fdda3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.transport.cache + +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import org.bukkit.Material +import org.bukkit.Material.END_ROD +import org.bukkit.Material.SPONGE +import org.bukkit.Material.WET_SPONGE +import org.bukkit.block.BlockFace + +class PowerTransportCache(holder: NetworkHolder<*>) : TransportCache(holder) { + private val powerNodeTypes = setOf( + PowerNode.SpongeNode, + PowerNode.EndRodNode + ) + + override fun getNodeType(material: Material): CachedNode? { + return powerNodeTypes.firstOrNull { it.isMatchingMaterial(material) } + } + + sealed interface PowerNode : CachedNode { + data object SpongeNode : PowerNode { + override fun isMatchingMaterial(material: Material): Boolean = material == SPONGE || material == WET_SPONGE + override fun getNextNodes(inputDirection: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(inputDirection) + } + + data object EndRodNode : PowerNode { + override fun isMatchingMaterial(material: Material): Boolean = material == END_ROD + override fun getNextNodes(inputDirection: BlockFace): Set = setOf(inputDirection) + } + + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt new file mode 100644 index 0000000000..315adadf8a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt @@ -0,0 +1,51 @@ +package net.horizonsend.ion.server.features.transport.cache + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import net.horizonsend.ion.server.features.transport.cache.state.CacheState +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import org.bukkit.Material +import org.bukkit.block.BlockFace + +abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network holder, works for now */) { + private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() + + fun isCached(at: BlockKey): Boolean = cache.containsKey(at) + + fun getCached(at: BlockKey): CachedNode? { + val state = cache[at] ?: return null + return when (state) { + is CacheState.Empty -> null + is CacheState.Present -> state.node + } + } + + fun cache(location: BlockKey, material: Material): CachedNode? { + val type = getNodeType(material) + val state = if (type == null) CacheState.Empty else CacheState.Present(type) + + cache[location] = state + return type + } + + abstract fun getNodeType(material: Material): CachedNode? + + fun getNextNodeLocations(location: BlockKey, from: BlockFace): Map { + val cachedAt = if (!isCached(location)) { + // If the requested node is not cached, cache the node at the location + val material = getBlockTypeSafe(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return mapOf() + cache(location, material) + } else getCached(location) // If it is already cached, this function will handle the empty node case + + if (cachedAt == null) return mapOf() + + return cachedAt.getNextNodes(from).associateWith { getRelative(location, it) } + } + + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt new file mode 100644 index 0000000000..59dfc04014 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.transport.cache.state + +import net.horizonsend.ion.server.features.transport.cache.CachedNode + +sealed interface CacheState { + data object Empty: CacheState + data class Present(val node: CachedNode): CacheState +} From 8309e3bd0a712138f238ac752150c84c422db532 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 9 Nov 2024 11:39:12 -0600 Subject: [PATCH 262/500] Add back more nodes to new system --- .../features/transport/cache/CachedNode.kt | 14 ++++++- .../transport/cache/PowerTransportCache.kt | 42 ++++++++++++++++--- .../transport/cache/TransportCache.kt | 8 ++-- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt index 308bf33351..0931fc7b86 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt @@ -9,6 +9,18 @@ interface CachedNode { /** * Gets the directions that should be checked for the next nodes + * + * Returns a map of block face to transfer priority **/ - fun getNextNodes(inputDirection: BlockFace): Set + fun getNextNodes(inputDirection: BlockFace): Collection> + + /** + * Adds any restrictions on transferring to another node + **/ + fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean + + /** + * Adds any restrictions on transferring from another node + **/ + fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt index ef788fdda3..4ea62699c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt @@ -2,16 +2,23 @@ package net.horizonsend.ion.server.features.transport.cache import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.axis +import org.bukkit.Axis import org.bukkit.Material +import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD +import org.bukkit.Material.IRON_BLOCK +import org.bukkit.Material.LAPIS_BLOCK +import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE import org.bukkit.Material.WET_SPONGE import org.bukkit.block.BlockFace class PowerTransportCache(holder: NetworkHolder<*>) : TransportCache(holder) { private val powerNodeTypes = setOf( - PowerNode.SpongeNode, - PowerNode.EndRodNode + PowerNode.SpongeNode::class.java, + PowerNode.EndRodNode::class.java, + ) override fun getNodeType(material: Material): CachedNode? { @@ -19,16 +26,41 @@ class PowerTransportCache(holder: NetworkHolder<*>) : TransportCache(holder) { } sealed interface PowerNode : CachedNode { + fun anyDirection(inputDirection: BlockFace) = ADJACENT_BLOCK_FACES.minus(inputDirection).map { it to 1 } + data object SpongeNode : PowerNode { + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true override fun isMatchingMaterial(material: Material): Boolean = material == SPONGE || material == WET_SPONGE - override fun getNextNodes(inputDirection: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(inputDirection) + override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) } - data object EndRodNode : PowerNode { + data class EndRodNode(val axis: Axis) : PowerNode { + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false override fun isMatchingMaterial(material: Material): Boolean = material == END_ROD - override fun getNextNodes(inputDirection: BlockFace): Set = setOf(inputDirection) + override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only + } + + data object PowerExtractorNode : PowerNode { + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = false + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true + override fun isMatchingMaterial(material: Material): Boolean = material == CRAFTING_TABLE + override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) } + data object PowerMergeNode : PowerNode { + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is SpongeNode + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is SpongeNode + override fun isMatchingMaterial(material: Material): Boolean = material == IRON_BLOCK || material == REDSTONE_BLOCK + override fun getNextNodes(inputDirection: BlockFace): Collection> = TODO() + } + data object PowerInvertedMergeNode : PowerNode { + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is EndRodNode + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is EndRodNode + override fun isMatchingMaterial(material: Material): Boolean = material == LAPIS_BLOCK + override fun getNextNodes(inputDirection: BlockFace): Collection> = TODO() + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt index 315adadf8a..24496e8c42 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt @@ -35,16 +35,16 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network abstract fun getNodeType(material: Material): CachedNode? - fun getNextNodeLocations(location: BlockKey, from: BlockFace): Map { + fun getNextNodeLocations(location: BlockKey, from: BlockFace): List> { val cachedAt = if (!isCached(location)) { // If the requested node is not cached, cache the node at the location - val material = getBlockTypeSafe(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return mapOf() + val material = getBlockTypeSafe(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return listOf() cache(location, material) } else getCached(location) // If it is already cached, this function will handle the empty node case - if (cachedAt == null) return mapOf() + if (cachedAt == null) return listOf() - return cachedAt.getNextNodes(from).associateWith { getRelative(location, it) } + return cachedAt.getNextNodes(from).map { (face, priority) -> Triple(face, getRelative(location, face), priority) } } From 1a15d7f470e78920ddedf0788bc6e31f1bf835d6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 9 Nov 2024 23:12:37 -0600 Subject: [PATCH 263/500] Halfway through implementation --- .../server/command/admin/IonChunkCommand.kt | 58 +---- .../manager/ChunkMultiblockManager.kt | 3 +- .../multiblock/manager/MultiblockManager.kt | 3 +- .../manager/ShipMultiblockManager.kt | 3 +- .../features/transport/cache/CachedNode.kt | 4 +- .../transport/cache/FluidTransportCache.kt | 10 + .../transport/cache/NodeCacheFactory.kt | 49 +++++ .../transport/cache/PowerTransportCache.kt | 205 ++++++++++++++++-- .../transport/cache/TransportCache.kt | 43 ++-- .../node/manager/ChunkTransportManager.kt | 45 ++-- .../node/manager/FluidNodeManager.kt | 4 +- .../transport/node/manager/NodeManager.kt | 77 +------ .../node/manager/PowerNodeManager.kt | 140 +----------- .../node/manager/ShipTransportManager.kt | 6 +- .../node/manager/TransportManager.kt | 11 +- .../manager/holders/ChunkNetworkHolder.kt | 146 +------------ .../node/manager/holders/NetworkHolder.kt | 18 +- .../node/manager/holders/ShipNetworkHolder.kt | 40 +--- .../features/transport/node/util/NodeUtils.kt | 16 +- .../server/features/world/chunk/IonChunk.kt | 1 - 20 files changed, 356 insertions(+), 526 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 34d2f71dea..f71be72a2f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode @@ -73,10 +74,10 @@ object IonChunkCommand : SLCommand() { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) - sender.information("${grid.nodes.size} covered position(s).") - sender.information("${grid.nodes.values.distinct().size} unique node(s).") + sender.information("${grid.getRawCache().size} covered position(s).") + sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") - grid.nodes.forEach { (t, u) -> + grid.getRawCache().forEach { (t, u) -> val vec = toVec3i(t) sender.highlightBlock(vec, 50L) } @@ -88,8 +89,8 @@ object IonChunkCommand : SLCommand() { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) - sender.information("${grid.nodes.size} covered position(s).") - sender.information("${grid.nodes.values.distinct().size} unique node(s).") + sender.information("${grid.getRawCache().size} covered position(s).") + sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") when (grid) { is PowerNodeManager -> { @@ -108,39 +109,12 @@ object IonChunkCommand : SLCommand() { sender.information("World has: ${ionChunk.world.ion.regionPositions.values.distinct().size} unique regions") } - @Subcommand("rebuild nodes") - @CommandCompletion("power") /* |item|gas") */ - fun rebuildNodes(sender: Player, network: NetworkType) { - val ionChunk = sender.chunk.ion() - - Tasks.async { - val grid = network.get(ionChunk) - - grid.nodes.clear() - - when (grid) { - is PowerNodeManager -> { - grid.extractors.clear() - grid.solarPanels.clear() - } - } - - for (x in ionChunk.originX ..ionChunk.originX + 15) { - for (z in ionChunk.originZ..ionChunk.originZ + 15) { - for (y in ionChunk.world.minHeight until ionChunk.world.maxHeight) { - grid.createNodeFromBlock(sender.world.getBlockAt(x, y, z)) - } - } - } - } - } - @Subcommand("get node key") fun getNode(sender: Player, key: Long, network: NetworkType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) - sender.information("Targeted node: ${grid.nodes[key]}") + sender.information("Targeted node: ${grid.getRawCache()[key]}") } @Subcommand("get node look") @@ -150,28 +124,18 @@ object IonChunkCommand : SLCommand() { val grid = network.get(ionChunk) val key = toBlockKey(targeted.x, targeted.y, targeted.z) - sender.information("Targeted node: ${grid.nodes[key]}") - } - - @Subcommand("get node look relations") - fun getNodeRelations(sender: Player, network: NetworkType) { - val targeted = sender.getTargetBlock(null, 10) - val ionChunk = targeted.chunk.ion() - val grid = network.get(ionChunk) - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - sender.information("${grid.nodes[key]?.getTransferableNodes()?.joinToString { it.javaClass.simpleName }}") + sender.information("Targeted node: ${grid.getRawCache()[key]}") } @Subcommand("test extractor") fun onTick(sender: Player) { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() - val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager + val grid = NetworkType.POWER.get(ionChunk) as PowerTransportCache val key = toBlockKey(targeted.x, targeted.y, targeted.z) - val node = grid.nodes[key] - if (node !is PowerExtractorNode) return + val node = grid.getCached(key) + if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) return grid.tickExtractor(node) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 6e534da1ad..9b17941ed3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.chunk.IonChunk @@ -40,7 +41,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag chunk.inner.minecraft.isUnsaved = true } - override fun getNetwork(type: NetworkType): NodeManager<*> { + override fun getNetwork(type: NetworkType): TransportCache { return type.get(chunk) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index b8c2db6173..d29b8dba44 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultibl import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -34,7 +35,7 @@ abstract class MultiblockManager(val log: Logger) { fun getAllMultiblockEntities() = multiblockEntities - abstract fun getNetwork(type: NetworkType): NodeManager<*> + abstract fun getNetwork(type: NetworkType): TransportCache abstract fun getSignUnsavedTime(): Long open fun markSignSaved() {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 7273b8ca00..2ceac31eb4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -40,7 +41,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override fun getSignUnsavedTime(): Long = 0 override fun markChanged() {} - override fun getNetwork(type: NetworkType): NodeManager<*> { + override fun getNetwork(type: NetworkType): TransportCache { return type.get(starship) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt index 0931fc7b86..cb34c003b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt @@ -4,9 +4,7 @@ import org.bukkit.Material import org.bukkit.block.BlockFace interface CachedNode { - // The backing material(s) of this node type - fun isMatchingMaterial(material: Material): Boolean - + val pathfindingResistance: Double /** * Gets the directions that should be checked for the next nodes * diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt new file mode 100644 index 0000000000..21f2ea76ea --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.transport.cache + +import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.util.NetworkType + +class FluidTransportCache(holder: NetworkHolder): TransportCache(holder) { + override val type: NetworkType = NetworkType.FLUID + override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() + .build() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt new file mode 100644 index 0000000000..373ab87f1d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt @@ -0,0 +1,49 @@ +package net.horizonsend.ion.server.features.transport.cache + +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe +import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe +import org.bukkit.Material +import org.bukkit.block.Block +import org.bukkit.block.data.BlockData +import kotlin.reflect.KClass + +class NodeCacheFactory private constructor(private val materialHandlers: Map>) { + fun cache(block: Block): CachedNode? { + val type = block.getTypeSafe() ?: return null + val materialFactory = materialHandlers[type] ?: return null + val blockData = getBlockDataSafe(block.world, block.x, block.y, block.z) ?: return null + + if (materialFactory.blockDataClass.isInstance(blockData)) return null + return materialFactory.construct(blockData) + } + + class Builder { + val materialHandlers = mutableMapOf>() + + inline fun addDataHandler(material: Material, noinline constructor: (T) -> CachedNode): Builder { + this.materialHandlers[material] = MaterialHandler(T::class, material, constructor) + return this + } + + fun addSimpleNode(material: Material, node: CachedNode): Builder { + this.materialHandlers[material] = MaterialHandler(BlockData::class, material) { node } + return this + } + + fun build(): NodeCacheFactory { + return NodeCacheFactory(materialHandlers) + } + } + + class MaterialHandler(val blockDataClass: KClass, val registeredMaterial: Material, val constructor: (T) -> CachedNode) { + fun construct(blockData: BlockData): CachedNode? { + if (blockDataClass.isInstance(blockData)) return null + @Suppress("UNCHECKED_CAST") + return constructor.invoke(blockData as T) + } + } + + companion object { + fun builder(): Builder = Builder() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt index 4ea62699c2..a99b53570d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt @@ -1,66 +1,231 @@ package net.horizonsend.ion.server.features.transport.cache +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode +import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode +import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode +import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.node.util.getIdealPath +import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import org.bukkit.Axis -import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD import org.bukkit.Material.IRON_BLOCK import org.bukkit.Material.LAPIS_BLOCK +import org.bukkit.Material.OBSERVER import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE -import org.bukkit.Material.WET_SPONGE import org.bukkit.block.BlockFace +import org.bukkit.block.data.type.Observer +import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod +import java.util.concurrent.Future +import kotlin.math.roundToInt -class PowerTransportCache(holder: NetworkHolder<*>) : TransportCache(holder) { - private val powerNodeTypes = setOf( - PowerNode.SpongeNode::class.java, - PowerNode.EndRodNode::class.java, - - ) - - override fun getNodeType(material: Material): CachedNode? { - return powerNodeTypes.firstOrNull { it.isMatchingMaterial(material) } - } +class PowerTransportCache(holder: NetworkHolder) : TransportCache(holder) { + override val type: NetworkType = NetworkType.POWER + override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) + .addSimpleNode(SPONGE, PowerNode.SpongeNode) + .addDataHandler(END_ROD) { PowerNode.EndRodNode(it.facing.axis) } + .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) + .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) + .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) + .addDataHandler(OBSERVER) { PowerNode.PowerFlowMeter(it.facing) } + .build() sealed interface PowerNode : CachedNode { - fun anyDirection(inputDirection: BlockFace) = ADJACENT_BLOCK_FACES.minus(inputDirection).map { it to 1 } + fun anyDirection(inputDirection: BlockFace) = ADJACENT_BLOCK_FACES.minus(inputDirection.oppositeFace).map { it to 1 } data object SpongeNode : PowerNode { + override val pathfindingResistance: Double = 1.0 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun isMatchingMaterial(material: Material): Boolean = material == SPONGE || material == WET_SPONGE override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) } data class EndRodNode(val axis: Axis) : PowerNode { + override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false - override fun isMatchingMaterial(material: Material): Boolean = material == END_ROD override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only } data object PowerExtractorNode : PowerNode { + override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = false override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun isMatchingMaterial(material: Material): Boolean = material == CRAFTING_TABLE override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) } data object PowerMergeNode : PowerNode { + override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is SpongeNode override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is SpongeNode - override fun isMatchingMaterial(material: Material): Boolean = material == IRON_BLOCK || material == REDSTONE_BLOCK - override fun getNextNodes(inputDirection: BlockFace): Collection> = TODO() + override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf( + inputDirection to 10, + *ADJACENT_BLOCK_FACES.minus(inputDirection).minus(inputDirection.oppositeFace).map { it to 1 }.toTypedArray() + ) } data object PowerInvertedMergeNode : PowerNode { + override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is EndRodNode override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is EndRodNode - override fun isMatchingMaterial(material: Material): Boolean = material == LAPIS_BLOCK - override fun getNextNodes(inputDirection: BlockFace): Collection> = TODO() + override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf( + inputDirection to 10, + *ADJACENT_BLOCK_FACES.minus(inputDirection).minus(inputDirection.oppositeFace).map { it to 1 }.toTypedArray() + ) + } + + data class PowerFlowMeter(val face: BlockFace) : PowerNode { + //TODO display + + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true + override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only + } + } + + fun tickExtractor(extractorNode: PowerNode.PowerExtractorNode): Future<*> = NewTransport.executor.submit { + val powerCheck = extractorNode.getTransferAmount() + if (powerCheck == 0) return@submit + + extractorNode.markTicked() + + val source = extractorNode.getSourcePool().filterNot { it.powerStorage.isEmpty() }.randomOrNull() ?: return@submit + + val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) + destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) + + if (destinations.isEmpty()) return@submit + + val transferred = minOf(source.powerStorage.getPower(), powerCheck) + val notRemoved = source.powerStorage.removePower(transferred) + val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) + + if (transferred == remainder) { + //TODO skip growing number of ticks if nothing to do + } + + if (remainder > 0) { + source.powerStorage.addPower(remainder) } } + + private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { + val powerCheck = solarPanelNode.tickAndGetPower() + if (powerCheck == 0) return@submit + + val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) + runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) + } +} + +// These methods are outside the class for speed + +fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } + +/** + * Runs the power transfer from the source to the destinations. pending rewrite + **/ +private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { + if (destinations.isEmpty()) return availableTransferPower + + val numDestinations = destinations.size + + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(source, destinations[it]) + }.getOrNull() } + + var maximumResistance: Double = -1.0 + + // Perform the calc & max find in the same loop + val pathResistance: Array = Array(numDestinations) { + val res = calculatePathResistance(paths[it]) + if (res != null && maximumResistance < res) maximumResistance = res + + res + } + + // All null, no paths found + if (maximumResistance == -1.0) return availableTransferPower + + var shareFactorSum = 0.0 + + // Get a parallel array containing the ascending order of resistances + val sortedIndexes = getSorted(pathResistance) + + val shareFactors: Array = Array(numDestinations) { index -> + val resistance = pathResistance[index] ?: return@Array null + val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) + shareFactorSum += fac + + fac + } + + var remainingPower = availableTransferPower + + for ((index, destination) in destinations.withIndex()) { + val shareFactor = shareFactors[index] ?: continue + val share = shareFactor / shareFactorSum + + val idealSend = (availableTransferPower * share).roundToInt() + val toSend = minOf(idealSend, getRemainingCapacity(destination)) + + // Amount of power that didn't fit + val remainder = destination.distributePower(toSend) + val realTaken = toSend - remainder + + remainingPower -= realTaken + completeChain(paths[index], realTaken) + + if (remainder == 0) continue + + // Get the proportion of the amount of power that sent compared to the ideal calculations. + val usedShare = realTaken.toDouble() / idealSend.toDouble() + // Use that to get a proportion of the share factor, and remove that from the sum. + val toRemove = shareFactor * usedShare + shareFactorSum -= toRemove + } + + return remainingPower +} + +private fun getRemainingCapacity(destination: PowerInputNode): Int { + return destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } +} + +private fun completeChain(path: Array?, transferred: Int) { + path?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(transferred) } +} + +// I hate this function but it works +fun getSorted(pathResistance: Array): IntArray { + // Store the shuffled indicies + val ranks = IntArray(pathResistance.size) { it } + val tempSorted = pathResistance.clone() + + for (index in ranks.indices) { + for (j in 0..< ranks.lastIndex) { + if ((tempSorted[j] ?: Double.MAX_VALUE) > (tempSorted[j + 1] ?: Double.MAX_VALUE)) { + val temp = tempSorted[j] + tempSorted[j] = tempSorted[j + 1] + tempSorted[j + 1] = temp + + val prev = ranks[j] + ranks[j] = prev + 1 + ranks[j + 1] = prev + } + } + } + + return ranks } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt index 24496e8c42..71978f2d22 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt @@ -3,18 +3,23 @@ package net.horizonsend.ion.server.features.transport.cache import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.transport.cache.state.CacheState import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe -import org.bukkit.Material +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import org.bukkit.block.Block import org.bukkit.block.BlockFace abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network holder, works for now */) { private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() + abstract val type: NetworkType + abstract val nodeFactory: NodeCacheFactory + fun isCached(at: BlockKey): Boolean = cache.containsKey(at) fun getCached(at: BlockKey): CachedNode? { @@ -25,27 +30,37 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network } } - fun cache(location: BlockKey, material: Material): CachedNode? { - val type = getNodeType(material) + fun getOrCache(location: BlockKey): CachedNode? { + if (isCached(location)) return getCached(location) + else return cache(location, getBlockIfLoaded(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return null) + } + + fun cache(location: BlockKey) { + val world = holder.getWorld() + val block = getBlockIfLoaded(world, getX(location), getY(location), getZ(location)) ?: return + cache(location, block) + } + + fun cache(location: BlockKey, block: Block): CachedNode? { + val type = nodeFactory.cache(block) val state = if (type == null) CacheState.Empty else CacheState.Present(type) cache[location] = state return type } - abstract fun getNodeType(material: Material): CachedNode? - fun getNextNodeLocations(location: BlockKey, from: BlockFace): List> { - val cachedAt = if (!isCached(location)) { - // If the requested node is not cached, cache the node at the location - val material = getBlockTypeSafe(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return listOf() - cache(location, material) - } else getCached(location) // If it is already cached, this function will handle the empty node case - - if (cachedAt == null) return listOf() - + val cachedAt = getOrCache(location) ?: return listOf() return cachedAt.getNextNodes(from).map { (face, priority) -> Triple(face, getRelative(location, face), priority) } } + fun invalidate(x: Int, y: Int, z: Int) { + return invalidate(toBlockKey(x, y, z)) + } + + fun invalidate(key: BlockKey) { + + } + fun getRawCache() = cache } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt index 0af716c10d..dbf2879ee1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt @@ -1,15 +1,18 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.Block import org.bukkit.block.data.BlockData class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { - override val powerNodeManager = ChunkNetworkHolder(this) { PowerNodeManager(it) } - override val fluidNodeManager = ChunkNetworkHolder(this) { FluidNodeManager(it) } + override val powerNodeManager = ChunkNetworkHolder(this) { PowerTransportCache(it) } + override val fluidNodeManager = ChunkNetworkHolder(this) { FluidTransportCache(it) } // val pipeGrid = PowerNodeManager(this) // TODO fun setup() { @@ -24,47 +27,27 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { NewTransport.removeTransportManager(this) } - fun save() { - powerNodeManager.save(chunk.inner.persistentDataContainer.adapterContext) - fluidNodeManager.save(chunk.inner.persistentDataContainer.adapterContext) - } - fun processBlockRemoval(key: BlockKey) { - powerNodeManager.network.processBlockRemoval(key) - fluidNodeManager.network.processBlockRemoval(key) + powerNodeManager.network.invalidate(key) + fluidNodeManager.network.invalidate(key) // pipeGrid.processBlockRemoval(key) } - fun processBlockRemovals(keys: Iterable) { - powerNodeManager.network.processBlockRemovals(keys) - fluidNodeManager.network.processBlockRemovals(keys) - } - - fun processBlockChange(new: Block) { - powerNodeManager.network.processBlockChange(new) - fluidNodeManager.network.processBlockChange(new) + fun processBlockChange(block: Block) { + powerNodeManager.network.invalidate(toBlockKey(block.x, block.y, block.z)) + fluidNodeManager.network.invalidate(toBlockKey(block.x, block.y, block.z)) // pipeGrid.processBlockAddition(key, new) } fun processBlockChange(position: BlockKey, data: BlockData) { - powerNodeManager.network.processBlockChange(position, data) - fluidNodeManager.network.processBlockChange(position, data) + powerNodeManager.network.invalidate(position) + fluidNodeManager.network.invalidate(position) // pipeGrid.processBlockAddition(key, new) } - fun processBlockChanges(changeMap: Map) { - powerNodeManager.network.processBlockChanges(changeMap) - fluidNodeManager.network.processBlockChanges(changeMap) - } - fun refreshBlock(position: BlockKey) { - powerNodeManager.network.processBlockChange(position) - fluidNodeManager.network.processBlockChange(position) + powerNodeManager.network.invalidate(position) + fluidNodeManager.network.invalidate(position) // pipeGrid.processBlockAddition(key, new) } - - fun processBlockChange(changed: Iterable) { - powerNodeManager.network.processBlockAdditions(changed) - fluidNodeManager.network.processBlockAdditions(changed) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index 79ce39815c..29529a38ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.transport.node.manager import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode @@ -13,7 +15,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import org.bukkit.NamespacedKey import java.util.concurrent.Future -class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { +class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val namespacedKey: NamespacedKey = FLUID_TRANSPORT override val type: NetworkType = NetworkType.FLUID override val nodeFactory = FluidNodeFactory(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt index 986ca4c70b..3b89f7156d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt @@ -30,81 +30,6 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { var ready: Boolean = false - open fun processBlockRemoval(key: BlockKey) { - val previousNode = nodes[key] ?: return - - previousNode.handlePositionRemoval(key) - holder.markUnsaved() - } - - open fun processBlockRemovals(keys: Iterable) { - var hits = 0 - - for (key in keys) { - val previousNode = nodes[key] ?: return - hits++ - - previousNode.handlePositionRemoval(key) - } - - if (hits > 0) holder.markUnsaved() - } - - open fun processBlockChange(new: Block) { - if (new.type.isAir) { - processBlockRemoval(toBlockKey(new.x, new.y, new.z)) - - return - } - - if (createNodeFromBlock(new)) holder.markUnsaved() - } - - open fun processBlockChange(position: BlockKey) { - val block = world.getBlockAt(getX(position), getY(position), getZ(position)) - - if (block.type.isAir) { - processBlockRemoval(position) - - return - } - - if (createNodeFromBlock(block)) holder.markUnsaved() - } - - open fun processBlockChange(position: BlockKey, data: BlockData) { - if (data.material.isAir) { - processBlockRemoval(position) - - return - } - - if (createNodeFromBlock(position, data)) holder.markUnsaved() - } - - open fun processBlockChanges(changeMap: Map) { - for ((position, data) in changeMap) { - if (data.material.isAir) { - processBlockRemoval(position) - - return - } - - if (createNodeFromBlock(position, data)) holder.markUnsaved() - } - } - - open fun processBlockAdditions(changed: Iterable) { - var hits = 0 - for (new in changed) { - if (createNodeFromBlock(new)) { - hits++ - } - } - - if (hits > 0) holder.markUnsaved() - } - /** * Handle the creation / loading of the node into memory **/ @@ -160,6 +85,6 @@ abstract class NodeManager(val holder: NetworkHolder<*>) { * Gets a node from this chunk, or a direct neighbor, if loaded **/ fun getNode(key: BlockKey, allowNeighborChunks: Boolean = true): TransportNode? { - return if (allowNeighborChunks) holder.getGlobalNode(key) else holder.getInternalNode(key) + return null } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt index da64838807..9c8f8239de 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.node.manager import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode @@ -18,7 +19,7 @@ import org.bukkit.NamespacedKey import java.util.concurrent.Future import kotlin.math.roundToInt -class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { +class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { override val type: NetworkType = NetworkType.POWER override val namespacedKey: NamespacedKey = POWER_TRANSPORT override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) @@ -35,142 +36,5 @@ class PowerNodeManager(holder: NetworkHolder) : NodeManager = NewTransport.executor.submit { - val powerCheck = extractorNode.getTransferAmount() - if (powerCheck == 0) return@submit - - extractorNode.markTicked() - - val source = extractorNode.getSourcePool().filterNot { it.powerStorage.isEmpty() }.randomOrNull() ?: return@submit - - val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) - destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) - - if (destinations.isEmpty()) return@submit - - val transferred = minOf(source.powerStorage.getPower(), powerCheck) - val notRemoved = source.powerStorage.removePower(transferred) - val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) - - if (transferred == remainder) { - //TODO skip growing number of ticks if nothing to do - } - - if (remainder > 0) { - source.powerStorage.addPower(remainder) - } - } - - private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { - val powerCheck = solarPanelNode.tickAndGetPower() - if (powerCheck == 0) return@submit - - val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) - runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) - } -} - -// These methods are outside the class for speed - -fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } - -/** - * Runs the power transfer from the source to the destinations. pending rewrite - **/ -private fun runPowerTransfer(source: TransportNode, destinations: List, availableTransferPower: Int): Int { - if (destinations.isEmpty()) return availableTransferPower - - val numDestinations = destinations.size - - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, destinations[it]) - }.getOrNull() } - - var maximumResistance: Double = -1.0 - - // Perform the calc & max find in the same loop - val pathResistance: Array = Array(numDestinations) { - val res = calculatePathResistance(paths[it]) - if (res != null && maximumResistance < res) maximumResistance = res - - res - } - - // All null, no paths found - if (maximumResistance == -1.0) return availableTransferPower - - var shareFactorSum = 0.0 - - // Get a parallel array containing the ascending order of resistances - val sortedIndexes = getSorted(pathResistance) - - val shareFactors: Array = Array(numDestinations) { index -> - val resistance = pathResistance[index] ?: return@Array null - val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) - shareFactorSum += fac - - fac - } - - var remainingPower = availableTransferPower - - for ((index, destination) in destinations.withIndex()) { - val shareFactor = shareFactors[index] ?: continue - val share = shareFactor / shareFactorSum - - val idealSend = (availableTransferPower * share).roundToInt() - val toSend = minOf(idealSend, getRemainingCapacity(destination)) - - // Amount of power that didn't fit - val remainder = destination.distributePower(toSend) - val realTaken = toSend - remainder - - remainingPower -= realTaken - completeChain(paths[index], realTaken) - - if (remainder == 0) continue - - // Get the proportion of the amount of power that sent compared to the ideal calculations. - val usedShare = realTaken.toDouble() / idealSend.toDouble() - // Use that to get a proportion of the share factor, and remove that from the sum. - val toRemove = shareFactor * usedShare - shareFactorSum -= toRemove - } - - return remainingPower -} - -private fun getRemainingCapacity(destination: PowerInputNode): Int { - return destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } -} - -private fun completeChain(path: Array?, transferred: Int) { - path?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(transferred) } -} - -// I hate this function but it works -fun getSorted(pathResistance: Array): IntArray { - // Store the shuffled indicies - val ranks = IntArray(pathResistance.size) { it } - val tempSorted = pathResistance.clone() - - for (index in ranks.indices) { - for (j in 0..< ranks.lastIndex) { - if ((tempSorted[j] ?: Double.MAX_VALUE) > (tempSorted[j + 1] ?: Double.MAX_VALUE)) { - val temp = tempSorted[j] - tempSorted[j] = tempSorted[j + 1] - tempSorted[j + 1] = temp - - val prev = ranks[j] - ranks[j] = prev + 1 - ranks[j + 1] = prev - } - } - } - - return ranks } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index ae9fb44270..113ead182c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -3,11 +3,13 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.node.manager.holders.ShipNetworkHolder class ShipTransportManager(val starship: Starship) : TransportManager() { - override val powerNodeManager = ShipNetworkHolder(this) { PowerNodeManager(it) } - override val fluidNodeManager = ShipNetworkHolder(this) { FluidNodeManager(it) } + override val powerNodeManager = ShipNetworkHolder(this) { PowerTransportCache(it) } + override val fluidNodeManager = ShipNetworkHolder(this) { FluidTransportCache(it) } init { load() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt index c7af0699ea..78b36efb84 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -1,13 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.manager +import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder abstract class TransportManager { - abstract val powerNodeManager: NetworkHolder - abstract val fluidNodeManager: NetworkHolder - - fun tick() { - powerNodeManager.network.tickTransport() - fluidNodeManager.network.tickTransport() - } + abstract val powerNodeManager: NetworkHolder + abstract val fluidNodeManager: NetworkHolder } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index d0b54f006f..599042aeb9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -2,9 +2,10 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.transport.cache.CachedNode +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -18,7 +19,7 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates -class ChunkNetworkHolder> private constructor (val manager: ChunkTransportManager) : NetworkHolder { +class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { override var network: T by Delegates.notNull(); private set constructor(manager: ChunkTransportManager, network: (ChunkNetworkHolder) -> T) : this(manager) { @@ -27,14 +28,14 @@ class ChunkNetworkHolder> private constructor (val manager: Ch override fun getWorld(): World = manager.chunk.world - override fun getGlobalNode(key: BlockKey): TransportNode? { + override fun getGlobalNode(key: BlockKey): CachedNode? { val chunkX = getX(key).shr(4) val chunkZ = getZ(key).shr(4) val isThisChunk = chunkX == manager.chunk.x && chunkZ == manager.chunk.z if (isThisChunk) { - return network.nodes[key] + return network.getOrCache(key) } val xDiff = manager.chunk.x - chunkX @@ -44,142 +45,11 @@ class ChunkNetworkHolder> private constructor (val manager: Ch if (zDiff > 1 || zDiff < -1) return null val chunk = IonChunk[getWorld(), chunkX, chunkZ] ?: return null - return network.type.get(chunk).nodes[key] + return network.type.get(chunk).getOrCache(key) } - override fun getInternalNode(key: BlockKey): TransportNode? { - return network.nodes[key] - } - - private val chunkPDC get() = manager.chunk.inner.persistentDataContainer - private val networkPDC get() = chunkPDC.get( - network.namespacedKey, - PersistentDataType.TAG_CONTAINER - ) ?: run { -// IonServer.slF4JLogger.warn("chunk ${manager.chunk.x}, ${manager.chunk.z} ${manager.chunk.world.name} didn't have transport information!") - - chunkPDC.adapterContext.newPersistentDataContainer() - } - - override fun handleLoad() { - // Load data sync - val good = loadData() - - Tasks.async { - val adapterContext = chunkPDC.adapterContext - - // Handle cases of data corruption - if (!good) { - network.clearData() - collectAllNodes() - - // Save rebuilt data - save(adapterContext) - } - - network.buildRelations() - network.finalizeNodes() - - network.ready = true - } - } - - override fun handleUnload() { - network.onUnload() - - save(manager.chunk.inner.persistentDataContainer.adapterContext) - } - - fun save(adapterContext: PersistentDataAdapterContext) { - val container = adapterContext.newPersistentDataContainer() - - val serializedNodes: MutableMap = mutableMapOf() - - network.nodes.values.distinct().forEach { node -> - serializedNodes[node] = node.serialize(adapterContext, node) - } - - if (serializedNodes.isNotEmpty()) { - manager.chunk.inner.minecraft.isUnsaved = true - } - - container.set(NamespacedKeys.NODES, PersistentDataType.TAG_CONTAINER_ARRAY, serializedNodes.values.toTypedArray()) - container.set(NamespacedKeys.DATA_VERSION, PersistentDataType.INTEGER, network.dataVersion) - network.saveAdditional(container) - - // Save the network PDC - chunkPDC.set(network.namespacedKey, PersistentDataType.TAG_CONTAINER, container) - } - - /** - * Load stored node data from the chunk - * - * @return Whether the data was intact, or up to date - **/ - fun loadData(): Boolean { - val version = networkPDC.getOrDefault(NamespacedKeys.DATA_VERSION, PersistentDataType.INTEGER, 0) - - if (version < network.dataVersion) { - IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained outdated data! It will be rebuilt") - return false - } - - // Deserialize once - val nodeData = networkPDC.getOrDefault(NamespacedKeys.NODES, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()).map { - runCatching { TransportNode.load(it, network) }.onFailure { - IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} contained corrupted data! It will be rebuilt") - it.printStackTrace() - }.getOrElse { - return false - } - } - - nodeData.forEach { runCatching { it.loadIntoNetwork() }.onFailure { - IonServer.slF4JLogger.error("${manager.chunk}'s ${javaClass.simpleName} loading node into network!") - it.printStackTrace() - return false - } } - - return true - } - - /** - * Build node data from an unregistered state - **/ - private fun collectAllNodes() { - // Parallel collect the nodes of each section - manager.chunk.sections.map { (y, _) -> - collectSectionNodes(y) - } - } - - /** - * Collect all nodes in this chunk section - * - * Iterate the section for possible nodes, handle creation - **/ - private fun collectSectionNodes(sectionY: Int) { - val originX = manager.chunk.originX - val originY = sectionY.shl(4) - manager.chunk.inner.world.minHeight - val originZ = manager.chunk.originZ - - for (x: Int in 0..15) { - val realX = originX + x - - for (y: Int in 0..15) { - val realY = originY + y - - for (z: Int in 0..15) { - val realZ = originZ + z - - network.createNodeFromBlock(manager.chunk.world.getBlockAt(realX, realY, realZ)) - } - } - } - } - - override fun markUnsaved() { - manager.chunk.inner.minecraft.isUnsaved = true + override fun getInternalNode(key: BlockKey): CachedNode? { + return network.getOrCache(key) } override fun getMultiblockManager(): MultiblockManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 870067e8ee..0521aab016 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.cache.CachedNode +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World -interface NetworkHolder > { +interface NetworkHolder { val network: T fun getWorld(): World @@ -16,24 +16,22 @@ interface NetworkHolder > { * * Existing data will be loaded from the chunk's persistent data container, relations between nodes will be built, and any finalization will be performed **/ - fun handleLoad() + fun handleLoad() {} /** * Logic for when the holder unloaded **/ - fun handleUnload() + fun handleUnload() {} /** * Get a node inside this network **/ - fun getInternalNode(key: BlockKey): TransportNode? + fun getInternalNode(key: BlockKey): CachedNode? /** * Method used to access nodes inside, and outside the network **/ - fun getGlobalNode(key: BlockKey): TransportNode? + fun getGlobalNode(key: BlockKey): CachedNode? - fun markUnsaved() - - abstract fun getMultiblockManager(): MultiblockManager + fun getMultiblockManager(): MultiblockManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index c2d9942bc2..ceb3745740 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -1,14 +1,16 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager +import net.horizonsend.ion.server.features.transport.cache.CachedNode +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World import kotlin.properties.Delegates -class ShipNetworkHolder>(val manager: ShipTransportManager) : NetworkHolder { +class ShipNetworkHolder(val manager: ShipTransportManager) : NetworkHolder { override var network: T by Delegates.notNull(); private set constructor(manager: ShipTransportManager, network: (ShipNetworkHolder) -> T) : this(manager) { @@ -18,39 +20,21 @@ class ShipNetworkHolder>(val manager: ShipTransportManager) : override fun getWorld(): World = manager.starship.world override fun handleLoad() { - captureNodes() + manager.starship.iterateBlocks { x, y, z -> + IonChunk[manager.starship.world, x, z]?.let { network.type.get(it).invalidate(x, y, z) } + network.cache(toBlockKey(x, y, z)) + } } - override fun handleUnload() { - network.clearData() - rebuildStaticNetwork() + override fun getInternalNode(key: BlockKey): CachedNode? { + return network.getCached(key) } - override fun getInternalNode(key: BlockKey): TransportNode? { - return network.nodes[key] - } - - override fun getGlobalNode(key: BlockKey): TransportNode? { + override fun getGlobalNode(key: BlockKey): CachedNode? { // Ship networks cannot access the outside world return getInternalNode(key) } - /** - * Build the transport network from the starship blocks - **/ - fun captureNodes() { - - } - - /** - * Rebuild the base networks in the chunks the ship occupies when it is released - **/ - fun rebuildStaticNetwork() { - - } - - override fun markUnsaved() {/* Do nothing */} - override fun getMultiblockManager(): MultiblockManager { return manager.starship.multiblockManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt index fb44c4ea8d..968ce3eb38 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt @@ -1,6 +1,9 @@ package net.horizonsend.ion.server.features.transport.node.util import net.horizonsend.ion.server.features.starship.active.ActiveStarship +import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager import net.horizonsend.ion.server.features.transport.node.manager.NodeManager @@ -111,23 +114,22 @@ fun > separateNodePositions(node: T): List> { return separated } - enum class NetworkType(val namespacedKey: NamespacedKey) { POWER(NamespacedKeys.POWER_TRANSPORT) { - override fun get(chunk: IonChunk): PowerNodeManager { + override fun get(chunk: IonChunk): PowerTransportCache { return chunk.transportNetwork.powerNodeManager.network } - override fun get(ship: ActiveStarship): PowerNodeManager { + override fun get(ship: ActiveStarship): PowerTransportCache { return ship.transportManager.powerNodeManager.network } }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { - override fun get(chunk: IonChunk): FluidNodeManager { + override fun get(chunk: IonChunk): FluidTransportCache { return chunk.transportNetwork.fluidNodeManager.network } - override fun get(ship: ActiveStarship): FluidNodeManager { + override fun get(ship: ActiveStarship): FluidTransportCache { return ship.transportManager.fluidNodeManager.network } }, @@ -135,8 +137,8 @@ enum class NetworkType(val namespacedKey: NamespacedKey) { ; - abstract fun get(chunk: IonChunk): NodeManager<*> - abstract fun get(ship: ActiveStarship): NodeManager<*> + abstract fun get(chunk: IonChunk): TransportCache + abstract fun get(ship: ActiveStarship): TransportCache companion object { private val byKey = entries.associateBy { it.namespacedKey } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index e3bdd178ba..59c45b12ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -75,7 +75,6 @@ class IonChunk( * Logic upon world save **/ fun save() { - transportNetwork.save() multiblockManager.save() } From dc652852cce7f9afb032e2869af72023b0d679a4 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 10 Nov 2024 12:25:59 -0600 Subject: [PATCH 264/500] Add extractor manager, migrate more code --- .../custom/items/misc/MultimeterItem.kt | 7 ++-- .../node/manager/ChunkTransportManager.kt | 3 ++ .../node/manager/ShipTransportManager.kt | 5 +++ .../node/manager/TransportManager.kt | 6 +++ .../extractors/ChunkExtractorManager.kt | 39 +++++++++++++++++++ .../manager/extractors/ExtractorManager.kt | 21 ++++++++++ .../extractors/ShipExtractorManager.kt | 33 ++++++++++++++++ .../manager/holders/ChunkNetworkHolder.kt | 13 +++---- .../node/manager/holders/NetworkHolder.kt | 3 ++ .../node/manager/holders/ShipNetworkHolder.kt | 5 +++ .../node/type/power/PowerExtractorNode.kt | 2 +- .../transport/node/util/NodePathfinding.kt | 29 +++++++++++--- .../server/features/world/chunk/IonChunk.kt | 6 +++ .../persistence/NamespacedKeys.kt | 1 + 14 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index b2f9fdeb43..435a768ef0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -18,6 +18,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -87,8 +88,8 @@ object MultimeterItem : CustomItem("Multimeter") { val networkTypeIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) val networkType = NetworkType.entries[networkTypeIndex] - val firstNode = networkType.get(firstChunk).getNode(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") - val secondNode = networkType.get(secondChunk).getNode(secondPoint) ?: return audience.information("There is no node at ${toVec3i(secondPoint)}") + val firstNode = networkType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") + val secondNode = networkType.get(secondChunk).getOrCache(secondPoint) ?: return audience.information("There is no node at ${toVec3i(secondPoint)}") val path = getIdealPath(audience, firstNode, secondNode) val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") @@ -110,7 +111,7 @@ object MultimeterItem : CustomItem("Multimeter") { /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ - private fun getIdealPath(audience: Audience, from: TransportNode, to: TransportNode): Array? { + private fun getIdealPath(audience: Audience, fromPos: BlockKey, toPos: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt index dbf2879ee1..84b7b1e0dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt @@ -3,6 +3,8 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ChunkExtractorManager +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -11,6 +13,7 @@ import org.bukkit.block.Block import org.bukkit.block.data.BlockData class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { + override val extractorManager: ExtractorManager = ChunkExtractorManager() override val powerNodeManager = ChunkNetworkHolder(this) { PowerTransportCache(it) } override val fluidNodeManager = ChunkNetworkHolder(this) { FluidTransportCache(it) } // val pipeGrid = PowerNodeManager(this) // TODO diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt index 113ead182c..56ed1f0d3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt @@ -5,9 +5,12 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ShipExtractorManager import net.horizonsend.ion.server.features.transport.node.manager.holders.ShipNetworkHolder class ShipTransportManager(val starship: Starship) : TransportManager() { + override val extractorManager: ShipExtractorManager = ShipExtractorManager(starship) + override val powerNodeManager = ShipNetworkHolder(this) { PowerTransportCache(it) } override val fluidNodeManager = ShipNetworkHolder(this) { FluidTransportCache(it) } @@ -17,10 +20,12 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { fun load() { NewTransport.registerTransportManager(this) + extractorManager.loadExtractors() } fun release() { NewTransport.removeTransportManager(this) + extractorManager.releaseExtractors() } fun displace(movement: StarshipMovement) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt index 78b36efb84..14c5bd834b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt @@ -2,9 +2,15 @@ package net.horizonsend.ion.server.features.transport.node.manager import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder abstract class TransportManager { + abstract val extractorManager: ExtractorManager abstract val powerNodeManager: NetworkHolder abstract val fluidNodeManager: NetworkHolder + + fun tick() { + + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt new file mode 100644 index 0000000000..fe8b0b6d9a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt @@ -0,0 +1,39 @@ +package net.horizonsend.ion.server.features.transport.node.manager.extractors + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import org.bukkit.persistence.PersistentDataType + +class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManager() { + var extractors = LongOpenHashSet() + + override fun getExtractors(): List { + return extractors.toList() + } + + override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { + if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != EXTRACTOR_TYPE) return false + if (!manager.chunk.isInBounds(x, y, z)) return false + extractors.add(toBlockKey(x, y, z)) + return true + } + + override fun isExtractor(key: BlockKey): Boolean { + return extractors.contains(key) + } + + private val pdc get() = manager.chunk.inner.persistentDataContainer + + override fun onLoad() { + val existing = pdc.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) ?: return + extractors = LongOpenHashSet(existing) + } + + override fun onSave() { + pdc.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.toLongArray()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt new file mode 100644 index 0000000000..e1ec6c3dde --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt @@ -0,0 +1,21 @@ +package net.horizonsend.ion.server.features.transport.node.manager.extractors + +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import org.bukkit.Material + +abstract class ExtractorManager { + abstract fun getExtractors(): List + fun registerExtractor(key: BlockKey, ensureExtractor: Boolean): Boolean = registerExtractor(getX(key), getY(key), getZ(key), ensureExtractor) + abstract fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean + abstract fun isExtractor(key: BlockKey): Boolean + + companion object { + val EXTRACTOR_TYPE = Material.CRAFTING_TABLE + } + + open fun onLoad() {} + open fun onSave() {} +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt new file mode 100644 index 0000000000..f5318eb4e8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt @@ -0,0 +1,33 @@ +package net.horizonsend.ion.server.features.transport.node.manager.extractors + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.features.starship.Starship +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe + +class ShipExtractorManager(val starship: Starship) : ExtractorManager() { + val extractors = LongOpenHashSet() + + override fun getExtractors(): List { + return extractors.toList() + } + + override fun isExtractor(key: BlockKey): Boolean { + return extractors.contains(key) + } + + override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { + if (ensureExtractor && getBlockTypeSafe(starship.world, x, y, z) != EXTRACTOR_TYPE) return false + extractors.add(toBlockKey(x, y, z)) + return true + } + + fun loadExtractors() { + starship.iterateBlocks { x, y, z -> registerExtractor(x, y, z, true) } + } + + fun releaseExtractors() { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index 599042aeb9..bba1530e31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -1,22 +1,15 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders -import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.minecraft import org.bukkit.World -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType import kotlin.properties.Delegates class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { @@ -55,4 +48,8 @@ class ChunkNetworkHolder private constructor (val manager: Ch override fun getMultiblockManager(): MultiblockManager { return manager.chunk.multiblockManager } + + override fun getExtractorManager(): ExtractorManager { + return manager.extractorManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index 0521aab016..fee1c0c164 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.node.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World @@ -34,4 +35,6 @@ interface NetworkHolder { fun getGlobalNode(key: BlockKey): CachedNode? fun getMultiblockManager(): MultiblockManager + + fun getExtractorManager(): ExtractorManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index ceb3745740..c3e6bf4702 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.cache.TransportCache import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager +import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -38,4 +39,8 @@ class ShipNetworkHolder(val manager: ShipTransportManager) : override fun getMultiblockManager(): MultiblockManager { return manager.starship.multiblockManager } + + override fun getExtractorManager(): ExtractorManager { + return manager.extractorManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index 8d2ac05127..ed38d2efe3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.transport.node.type.power import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks +import net.horizonsend.ion.server.features.transport.cache.getPowerInputs import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.manager.getPowerInputs import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index 8904fc92f5..46b27e9715 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -2,8 +2,12 @@ package net.horizonsend.ion.server.features.transport.node.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import org.bukkit.block.BlockFace import java.util.PriorityQueue import kotlin.math.roundToInt @@ -87,7 +91,7 @@ fun getNeighbors(parent: PathfindingNodeWrapper, destination: TransportNode): Ar val parentParent = parent.parent val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { parent.node.getNextNodes(parentParent.node, destination) - } else parent.node.cachedTransferable + } else parent.node.getNextNodes() return Array(transferable.size) { val neighbor = transferable[it] @@ -103,14 +107,27 @@ fun getNeighbors(parent: PathfindingNodeWrapper, destination: TransportNode): Ar // The heuristic used for the algorithm in this case is the distance from the node to the destination, which is typical, // But it also includes the pathfinding resistance to try to find the least resistant path. -fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: TransportNode): Int { - val resistance = wrapper.node.getPathfindingResistance(wrapper.parent?.node, null) - return wrapper.node.getDistance(destination).roundToInt() + resistance +fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: BlockKey): Int { + val resistance = wrapper.node.pathfindingResistance + return (toVec3i(wrapper.pos).distance(toVec3i(destination)) + resistance).roundToInt() } -data class PathfindingNodeWrapper(val node: TransportNode, var parent: PathfindingNodeWrapper?, var g: Int, var f: Int) { +/** + * @param pos The position of this node in the path + * @param node The cached node at this position + * @param parent The parent node + * @param offset The offset direction between the parent and this node + **/ +data class PathfindingNodeWrapper( + val pos: BlockKey, + val node: CachedNode, + var parent: PathfindingNodeWrapper?, + var offset: BlockFace, + var g: Int, + var f: Int +) { // Compiles the path - fun buildPath(): Array { + fun buildPath(): Array { val list = mutableListOf(this.node) var current: PathfindingNodeWrapper? = this diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 59c45b12ec..dcfcb9d5c1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -180,6 +180,12 @@ class IonChunk( /** Mark this chunk as needing to be saved */ fun markUnsaved() { inner.minecraft.isUnsaved = true } + fun isInBounds(x: Int, y: Int, z: Int): Boolean { + if (!(0..15).contains(x - originX)) return false + if (!(0..15).contains(z - originZ)) return false + return (world.minHeight..< world.maxHeight).contains(y) + } + override fun toString(): String { return "IonChunk[$x, $z @ ${world.name}]" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index cb47ca6e71..6c0cfd1358 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -96,6 +96,7 @@ object NamespacedKeys { val NODE_COVERED_POSITIONS = key("node_covered_positions") val AXIS = key("axis") + val EXTRACTORS = key("extractors") val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") val SOLAR_CELL_DETECTORS = key("solar_cell_detectors") From 5b5dd4462cb26fa0ae11bd0bc82b946bb7934f3d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 10 Nov 2024 14:22:00 -0600 Subject: [PATCH 265/500] Fixing up --- .../custom/items/misc/MultimeterItem.kt | 59 ++++----- .../features/transport/GlobalNodeManager.kt | 116 ------------------ .../server/features/transport/IonChangeSet.kt | 9 +- .../server/features/transport/NewTransport.kt | 7 ++ .../transport/cache/NodeCacheFactory.kt | 11 +- .../transport/cache/PowerTransportCache.kt | 54 ++++---- .../transport/cache/TransportCache.kt | 27 +++- .../configuration/TransportConfiguration.kt | 4 +- .../node/manager/ChunkTransportManager.kt | 11 +- .../manager/holders/ChunkNetworkHolder.kt | 2 +- .../node/manager/holders/NetworkHolder.kt | 2 +- .../node/manager/holders/ShipNetworkHolder.kt | 2 +- .../transport/node/util/NodePathfinding.kt | 66 +++++----- .../server/features/world/chunk/IonChunk.kt | 4 + .../miscellaneous/registrations/Listeners.kt | 2 - 15 files changed, 135 insertions(+), 241 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 435a768ef0..047e00ac92 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -6,12 +6,12 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode +import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.node.util.NetworkType import net.horizonsend.ion.server.features.transport.node.util.PathfindingNodeWrapper import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.node.util.getHeuristic +import net.horizonsend.ion.server.features.transport.node.util.getNeighbors import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_VARIANT @@ -30,6 +30,7 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration import org.bukkit.Material import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent @@ -83,17 +84,15 @@ object MultimeterItem : CustomItem("Multimeter") { val firstPoint = itemStack.itemMeta.persistentDataContainer.get(X, LONG) ?: return val firstChunk = IonChunk[world, getX(firstPoint).shr(4), getZ(firstPoint).shr(4)] ?: return val secondPoint = itemStack.itemMeta.persistentDataContainer.get(Z, LONG) ?: return - val secondChunk = IonChunk[world, getX(secondPoint).shr(4), getZ(secondPoint).shr(4)] ?: return val networkTypeIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) val networkType = NetworkType.entries[networkTypeIndex] val firstNode = networkType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") - val secondNode = networkType.get(secondChunk).getOrCache(secondPoint) ?: return audience.information("There is no node at ${toVec3i(secondPoint)}") - val path = getIdealPath(audience, firstNode, secondNode) + val path = getIdealPath(world, networkType, audience, firstPoint, firstNode, secondPoint) val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") - audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${secondNode.javaClass.simpleName} at ${toVec3i(secondPoint)} is $resistance") + audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${toVec3i(secondPoint)} at ${toVec3i(secondPoint)} is $resistance") } private fun cycleNetworks(audience: Audience, world: World, itemStack: ItemStack) { @@ -111,7 +110,7 @@ object MultimeterItem : CustomItem("Multimeter") { /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ - private fun getIdealPath(audience: Audience, fromPos: BlockKey, toPos: BlockKey): Array? { + private fun getIdealPath(world: World, type: NetworkType, audience: Audience, fromPos: BlockKey, fromNode: CachedNode, toPos: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -127,7 +126,16 @@ object MultimeterItem : CustomItem("Multimeter") { queueSet.remove(wrapper.node.hashCode()) } - queueAdd(PathfindingNodeWrapper(from, null, 0, 0)) + queueAdd(PathfindingNodeWrapper( + world = world, + pos = fromPos, + node = fromNode, + parent = null, + offset = BlockFace.SELF, + type = type, + g = 0, + f = 0 + )) val visited = IntOpenHashSet() @@ -137,24 +145,24 @@ object MultimeterItem : CustomItem("Multimeter") { while (queue.isNotEmpty() && iterations < 150) { iterations++ val current = queue.minBy { it.f } - Tasks.syncDelay(iterations) { audience.highlightBlock(current.node.getCenter(), 5L) } - audience.information("current: ${current.node.javaClass.simpleName} at ${current.node.getCenter()}") - if (current.node == to) return current.buildPath() + Tasks.syncDelay(iterations) { audience.highlightBlock(toVec3i(current.pos), 5L) } + audience.information("current: ${current.node.javaClass.simpleName} at ${toVec3i(current.pos)}") + if (current.pos == toPos) return current.buildPath() queueRemove(current) visited.add(current.node.hashCode()) - val neighbors = getNeighborsB(audience, current, to) + val neighbors = getNeighbors(current) if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { - audience.information("new neighbor: ${newNeighbor.node} at ${newNeighbor.node.getCenter()}") + audience.information("new neighbor: ${newNeighbor.node} at ${toVec3i(newNeighbor.pos)}") if (visited.contains(newNeighbor.node.hashCode())) { audience.information("conmtinue") continue } - newNeighbor.f = (newNeighbor.g + getHeuristic(newNeighbor, to)) + newNeighbor.f = (newNeighbor.g + getHeuristic(newNeighbor, toPos)) if (queueSet.contains(newNeighbor.node.hashCode())) { audience.information("Existing in queue") @@ -175,27 +183,4 @@ object MultimeterItem : CustomItem("Multimeter") { return null } - - // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution - private fun getNeighborsB(audience: Audience, parent: PathfindingNodeWrapper, destination: TransportNode): Array { - val parentParent = parent.parent - audience.information("Parent: ${parent.node.getTransferableNodes()}") - - val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { - parent.node.getNextNodes(parentParent.node, destination) - } else parent.node.cachedTransferable - - audience.information("New transferable: ${transferable.joinToString { it.javaClass.simpleName }}") - - return Array(transferable.size) { - val neighbor = transferable[it] - - PathfindingNodeWrapper( - node = neighbor, - parent = parent, - g = parent.g + parent.node.getDistance(neighbor).toInt(), - f = 1 - ) - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt deleted file mode 100644 index e7cb21b033..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/GlobalNodeManager.kt +++ /dev/null @@ -1,116 +0,0 @@ -package net.horizonsend.ion.server.features.transport - -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.Chunk -import org.bukkit.World -import org.bukkit.block.Block -import org.bukkit.block.data.BlockData -import org.bukkit.event.EventHandler -import org.bukkit.event.block.BlockBreakEvent -import org.bukkit.event.block.BlockPistonExtendEvent -import org.bukkit.event.block.BlockPistonRetractEvent -import org.bukkit.event.block.BlockPlaceEvent - -object GlobalNodeManager : SLEventListener() { - @EventHandler - fun onBlockBreak(event: BlockBreakEvent) { - val world = event.block.world - val key = toBlockKey(event.block.x, event.block.y, event.block.z) - - handleBlockRemoval(world, key) - } - - @EventHandler - fun onBlockPlace(event: BlockPlaceEvent) { - handleBlockChange(event.block) - } - - @EventHandler - fun onPistonExtend(event: BlockPistonExtendEvent) { - // Delay 1 tick - Tasks.sync { event.blocks.forEach { - handleBlockRemoval(it.world, toBlockKey(it.x, it.y, it.z)) - handleBlockChange(it) - }} - } - - @EventHandler - fun onPistonRetract(event: BlockPistonRetractEvent) { - // Delay 1 tick - Tasks.sync { event.blocks.forEach { - handleBlockRemoval(it.world, toBlockKey(it.x, it.y, it.z)) - handleBlockChange(it) - }} - } - - fun handleBlockChange(new: Block) { - val chunkX = new.x.shr(4) - val chunkZ = new.z.shr(4) - - val chunk = new.world.ion.getChunk(chunkX, chunkZ) ?: return - chunk.transportNetwork.processBlockChange(new) - } - - fun handleBlockChange(world: World, position: BlockKey, data: BlockData) { - val chunkX = getX(position).shr(4) - val chunkZ = getZ(position).shr(4) - - val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return - chunk.transportNetwork.processBlockChange(position, data) - } - - fun handleBlockChanges(world: World, changeMap: Map) { - val byChunk = changeMap.entries.groupBy { - Chunk.getChunkKey(getX(it.key), getZ(it.key)) - } - - for ((chunkKey, changes) in byChunk) { - val chunk = IonChunk[world, chunkKey] ?: continue - - for ((position, data) in changes) { - chunk.transportNetwork.processBlockChange(position, data) - } - } - } - - fun refreshBlock(world: World, position: BlockKey) { - val chunkX = getX(position).shr(4) - val chunkZ = getZ(position).shr(4) - - val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return - chunk.transportNetwork.refreshBlock(position) - } - - fun handleBlockAdditions(newBlocks: Iterable) { - for (new in newBlocks) { - handleBlockChange(new) - } - } - - fun handleBlockRemoval(world: World, key: BlockKey) { - val chunkX = getX(key).shr(4) - val chunkZ = getZ(key).shr(4) - - val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return - - chunk.transportNetwork.processBlockRemoval(key) - } - - fun handleBlockRemovals(world: World, keys: Iterable) { - for (key in keys) { - val chunkX = getX(key).shr(4) - val chunkZ = getZ(key).shr(4) - - val chunk = world.ion.getChunk(chunkX, chunkZ) ?: return - - chunk.transportNetwork.processBlockRemoval(key) - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt index cb6a14b01d..ff682b292c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt @@ -9,7 +9,6 @@ import com.sk89q.worldedit.world.biome.BiomeType import com.sk89q.worldedit.world.block.BlockTypesCache import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.block.Sign import java.util.Collections @@ -22,15 +21,9 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { counter++ addWriteTask { - val data = BukkitAdapter.adapt(BlockTypesCache.states[combinedTo]) + NewTransport.invalidateCache(bukkitWorld, x, y, z) val type = BukkitAdapter.adapt(BlockTypesCache.states[combinedTo].blockType) - GlobalNodeManager.handleBlockChange( - bukkitWorld, - toBlockKey(x, y, z), - data - ) - if (type.isWallSign) processMultiblock(x, y, z) if (type.isAir) removeMultiblock(x, y, z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 76da821c7f..abf8f05552 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -3,7 +3,9 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.transport.node.manager.TransportManager import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import org.bukkit.World import java.util.Timer import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ExecutorService @@ -43,4 +45,9 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t fun removeTransportManager(manager: TransportManager) { transportManagers.remove(manager) } + + fun invalidateCache(world: World, x: Int, y: Int, z: Int) { + val chunk = IonChunk[world, x.shr(4), z.shr(4)] ?: return + chunk.transportNetwork.invalidateCache(x, y, z) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt index 373ab87f1d..4bffef4af3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt @@ -13,7 +13,7 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map>() inline fun addDataHandler(material: Material, noinline constructor: (T) -> CachedNode): Builder { - this.materialHandlers[material] = MaterialHandler(T::class, material, constructor) + this.materialHandlers[material] = MaterialHandler(T::class, constructor) return this } fun addSimpleNode(material: Material, node: CachedNode): Builder { - this.materialHandlers[material] = MaterialHandler(BlockData::class, material) { node } + this.materialHandlers[material] = MaterialHandler(BlockData::class) { node } return this } @@ -35,9 +35,8 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val blockDataClass: KClass, val registeredMaterial: Material, val constructor: (T) -> CachedNode) { - fun construct(blockData: BlockData): CachedNode? { - if (blockDataClass.isInstance(blockData)) return null + class MaterialHandler(val blockDataClass: KClass, val constructor: (T) -> CachedNode) { + fun construct(blockData: BlockData): CachedNode { @Suppress("UNCHECKED_CAST") return constructor.invoke(blockData as T) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt index a99b53570d..d290c2780e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt @@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode @@ -14,6 +13,7 @@ import net.horizonsend.ion.server.features.transport.node.util.getIdealPath import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD @@ -22,6 +22,7 @@ import org.bukkit.Material.LAPIS_BLOCK import org.bukkit.Material.OBSERVER import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE +import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod @@ -95,29 +96,24 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor } fun tickExtractor(extractorNode: PowerNode.PowerExtractorNode): Future<*> = NewTransport.executor.submit { - val powerCheck = extractorNode.getTransferAmount() - if (powerCheck == 0) return@submit - - extractorNode.markTicked() - - val source = extractorNode.getSourcePool().filterNot { it.powerStorage.isEmpty() }.randomOrNull() ?: return@submit - - val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) - destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) - - if (destinations.isEmpty()) return@submit - - val transferred = minOf(source.powerStorage.getPower(), powerCheck) - val notRemoved = source.powerStorage.removePower(transferred) - val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) - - if (transferred == remainder) { - //TODO skip growing number of ticks if nothing to do - } - - if (remainder > 0) { - source.powerStorage.addPower(remainder) - } +// val source = extractorNode.getSourcePool().filterNot { it.powerStorage.isEmpty() }.randomOrNull() ?: return@submit +// +// val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) +// destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) +// +// if (destinations.isEmpty()) return@submit +// +// val transferred = minOf(source.powerStorage.getPower(), powerCheck) +// val notRemoved = source.powerStorage.removePower(transferred) +// val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) +// +// if (transferred == remainder) { +// //TODO skip growing number of ticks if nothing to do +// } +// +// if (remainder > 0) { +// source.powerStorage.addPower(remainder) +// } } private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { @@ -125,7 +121,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor if (powerCheck == 0) return@submit val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) - runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) +// runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) } } @@ -136,13 +132,13 @@ fun getPowerInputs(origin: TransportNode) = getNetworkDestinations, availableTransferPower: Int): Int { +private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: CachedNode, destinations: List, availableTransferPower: Int): Int { if (destinations.isEmpty()) return availableTransferPower val numDestinations = destinations.size - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, destinations[it]) + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(world, NetworkType.POWER, sourceType, sourcePos, destinations[it].position) }.getOrNull() } var maximumResistance: Double = -1.0 @@ -203,7 +199,7 @@ private fun getRemainingCapacity(destination: PowerInputNode): Int { return destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } } -private fun completeChain(path: Array?, transferred: Int) { +private fun completeChain(path: Array?, transferred: Int) { path?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(transferred) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt index 71978f2d22..f1e041afd3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.transport.cache.state.CacheState import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -42,25 +43,39 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network } fun cache(location: BlockKey, block: Block): CachedNode? { + println("Caching") val type = nodeFactory.cache(block) + println("Type: $type") val state = if (type == null) CacheState.Empty else CacheState.Present(type) cache[location] = state return type } - fun getNextNodeLocations(location: BlockKey, from: BlockFace): List> { - val cachedAt = getOrCache(location) ?: return listOf() - return cachedAt.getNextNodes(from).map { (face, priority) -> Triple(face, getRelative(location, face), priority) } - } - fun invalidate(x: Int, y: Int, z: Int) { return invalidate(toBlockKey(x, y, z)) } fun invalidate(key: BlockKey) { - + cache.remove(key) } fun getRawCache() = cache + + fun getNextNodes(backwards: BlockFace, parentPos: BlockKey, parentType: CachedNode): Map { + val adjacent = ADJACENT_BLOCK_FACES.minus(backwards) + + val map = mutableMapOf() + + for (adjacentFace in adjacent) { + val pos = getRelative(parentPos, adjacentFace) + val cached = holder.getOrCacheGlobalNode(pos) ?: continue + + if (!cached.canTransferFrom(parentType, adjacentFace) || !parentType.canTransferTo(cached, adjacentFace)) continue + + map[adjacentFace] = cached + } + + return map + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt index 0843a9db56..76745d4a74 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt @@ -6,6 +6,4 @@ import kotlinx.serialization.Serializable data class TransportConfiguration( val extractorTickIntervalMS: Long = 2000, val maxPowerRemovedPerExtractorTick: Int = 1000 -) { - -} +) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt index 84b7b1e0dd..a9952a0c08 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt @@ -13,7 +13,7 @@ import org.bukkit.block.Block import org.bukkit.block.data.BlockData class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { - override val extractorManager: ExtractorManager = ChunkExtractorManager() + override val extractorManager: ExtractorManager = ChunkExtractorManager(this) override val powerNodeManager = ChunkNetworkHolder(this) { PowerTransportCache(it) } override val fluidNodeManager = ChunkNetworkHolder(this) { FluidTransportCache(it) } // val pipeGrid = PowerNodeManager(this) // TODO @@ -30,6 +30,15 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { NewTransport.removeTransportManager(this) } + fun invalidateCache(x: Int, y: Int, z: Int) { + invalidateCache(toBlockKey(x, y, z)) + } + + fun invalidateCache(key: BlockKey) { + powerNodeManager.network.invalidate(key) + fluidNodeManager.network.invalidate(key) + } + fun processBlockRemoval(key: BlockKey) { powerNodeManager.network.invalidate(key) fluidNodeManager.network.invalidate(key) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt index bba1530e31..b02981f99a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt @@ -21,7 +21,7 @@ class ChunkNetworkHolder private constructor (val manager: Ch override fun getWorld(): World = manager.chunk.world - override fun getGlobalNode(key: BlockKey): CachedNode? { + override fun getOrCacheGlobalNode(key: BlockKey): CachedNode? { val chunkX = getX(key).shr(4) val chunkZ = getZ(key).shr(4) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt index fee1c0c164..a490577f62 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt @@ -32,7 +32,7 @@ interface NetworkHolder { /** * Method used to access nodes inside, and outside the network **/ - fun getGlobalNode(key: BlockKey): CachedNode? + fun getOrCacheGlobalNode(key: BlockKey): CachedNode? fun getMultiblockManager(): MultiblockManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt index c3e6bf4702..816ab15416 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt @@ -31,7 +31,7 @@ class ShipNetworkHolder(val manager: ShipTransportManager) : return network.getCached(key) } - override fun getGlobalNode(key: BlockKey): CachedNode? { + override fun getOrCacheGlobalNode(key: BlockKey): CachedNode? { // Ship networks cannot access the outside world return getInternalNode(key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index 46b27e9715..baccb9c1d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -4,9 +4,13 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import org.bukkit.World import org.bukkit.block.BlockFace import java.util.PriorityQueue import kotlin.math.roundToInt @@ -35,7 +39,7 @@ inline fun getNetworkDestinations(origin: TransportNo /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ -fun getIdealPath(from: TransportNode, to: TransportNode): Array? { +fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: BlockKey, to: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -51,7 +55,16 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? queueSet.remove(wrapper.node.hashCode()) } - queueAdd(PathfindingNodeWrapper(from, null, 0, 0)) + queueAdd(PathfindingNodeWrapper( + world = world, + pos = fromPos, + node = fromType, + parent = null, + offset = BlockFace.SELF, + type = type, + g = 0, + f = 0 + )) val visited = IntOpenHashSet() @@ -62,12 +75,12 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? iterations++ val current = queue.minBy { it.f } - if (current.node == to) return current.buildPath() + if (current.pos == to) return current.buildPath() queueRemove(current) visited.add(current.node.hashCode()) - for (neighbor in getNeighbors(current, to)) { + for (neighbor in getNeighbors(current)) { if (visited.contains(neighbor.node.hashCode())) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) @@ -87,19 +100,21 @@ fun getIdealPath(from: TransportNode, to: TransportNode): Array? } // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution -fun getNeighbors(parent: PathfindingNodeWrapper, destination: TransportNode): Array { - val parentParent = parent.parent - val transferable = if (parentParent != null && parent.node is PowerPathfindingNode) { - parent.node.getNextNodes(parentParent.node, destination) - } else parent.node.getNextNodes() +fun getNeighbors(current: PathfindingNodeWrapper): Array { + val transferable = current.network?.getNextNodes(current.offset, current.pos, current.node)?.toList() ?: return arrayOf() return Array(transferable.size) { - val neighbor = transferable[it] + val (neighborFace, neighborType) = transferable[it] + val neighborPos = getRelative(current.pos, neighborFace) PathfindingNodeWrapper( - node = neighbor, - parent = parent, - g = parent.g + parent.node.getDistance(neighbor).toInt(), + world = current.world, + pos = neighborPos, + node = neighborType, + parent = current, + type = current.type, + offset = neighborFace, + g = current.g + 1, f = 1 ) } @@ -119,14 +134,18 @@ fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: BlockKey): Int { * @param offset The offset direction between the parent and this node **/ data class PathfindingNodeWrapper( + val world: World, val pos: BlockKey, val node: CachedNode, + val type: NetworkType, var parent: PathfindingNodeWrapper?, var offset: BlockFace, var g: Int, var f: Int ) { - // Compiles the path + val network get() = IonChunk.getFromWorldCoordinates(world, getX(pos), getZ(pos))?.let { type.get(it) } + + // Compiles the path fun buildPath(): Array { val list = mutableListOf(this.node) var current: PathfindingNodeWrapper? = this @@ -164,19 +183,6 @@ data class PathfindingNodeWrapper( // } -fun calculatePathResistance(path: Array?): Double? { - if (path == null) return null - - var sum = 0.0 - - for (index in path.indices) { - val current = path[index] - - sum += current.getPathfindingResistance( - previousNode = path.getOrNull(index - 1), - nextNode = path.getOrNull(index + 1) - ) - } - - return sum +fun calculatePathResistance(path: Array?): Double? { + return path?.sumOf { it.pathfindingResistance } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index dcfcb9d5c1..e3d1e976ac 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -169,6 +169,10 @@ class IonChunk( fun getXFromKey(key: Long): Int = key.toInt() fun getZFromKey(key: Long): Int = (key shr 32).toInt() + + fun getFromWorldCoordinates(world: World, x: Int, z: Int): IonChunk? { + return get(world, x.shr(4), z.shr(4)) + } } fun iterateBlocks(consumer: Consumer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index a964fa9d14..09cf4e98e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -13,7 +13,6 @@ import net.horizonsend.ion.server.features.progression.achievements.AchievementL import net.horizonsend.ion.server.features.space.encounters.EncounterManager import net.horizonsend.ion.server.features.starship.control.controllers.player.ActivePlayerController import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeaconManager -import net.horizonsend.ion.server.features.transport.GlobalNodeManager import net.horizonsend.ion.server.features.waypoint.WaypointListeners import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.generation.WorldGenerationManager @@ -83,7 +82,6 @@ val listeners: List = listOf( ActivePlayerController.Companion, TransportManager, PersonalTransporterManager, - GlobalNodeManager, MultiblockEntities, // Achievement Listeners From 626b699fd67030a84811041c23aee1f4fd9d50e8 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 10 Nov 2024 20:28:14 -0600 Subject: [PATCH 266/500] Get pathfinding working again --- .../custom/items/misc/MultimeterItem.kt | 11 +-- .../type/misc/DecomposerMultiblock.kt | 6 -- .../transport/cache/NodeCacheFactory.kt | 2 +- .../transport/cache/PowerTransportCache.kt | 13 ++- .../transport/cache/TransportCache.kt | 20 ----- .../node/manager/FluidNodeManager.kt | 15 +--- .../node/type/power/PowerExtractorNode.kt | 9 -- .../transport/node/util/NodePathfinding.kt | 84 +++++++++++++++---- 8 files changed, 87 insertions(+), 73 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 047e00ac92..3049faa7e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.custom.items.misc import it.unimi.dsi.fastutil.ints.IntOpenHashSet +import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError @@ -137,7 +138,7 @@ object MultimeterItem : CustomItem("Multimeter") { f = 0 )) - val visited = IntOpenHashSet() + val visited = LongOpenHashSet() // Safeguard var iterations = 0L @@ -150,14 +151,14 @@ object MultimeterItem : CustomItem("Multimeter") { if (current.pos == toPos) return current.buildPath() queueRemove(current) - visited.add(current.node.hashCode()) + visited.add(current.pos) - val neighbors = getNeighbors(current) + val neighbors = getNeighbors(current, audience) if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { - audience.information("new neighbor: ${newNeighbor.node} at ${toVec3i(newNeighbor.pos)}") - if (visited.contains(newNeighbor.node.hashCode())) { + audience.information("new neighbor: ${newNeighbor} at ${toVec3i(newNeighbor.pos)}") + if (visited.contains(newNeighbor.pos)) { audience.information("conmtinue") continue } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt index 452c0823bc..5f9557c829 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DecomposerMultiblock.kt @@ -33,7 +33,6 @@ import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.block.Action import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.persistence.PersistentDataAdapterContext object DecomposerMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { override val name: String = "decomposer" @@ -133,11 +132,6 @@ object DecomposerMultiblock : Multiblock(), EntityMultiblock>() inline fun addDataHandler(material: Material, noinline constructor: (T) -> CachedNode): Builder { - this.materialHandlers[material] = MaterialHandler(T::class, constructor) + this.materialHandlers[material] = MaterialHandler(T::class, constructor) return this } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt index d290c2780e..185b841f77 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.transport.cache -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode @@ -93,6 +91,13 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only } + + data class PowerInputNode(val pos: BlockKey) : PowerNode { + override val pathfindingResistance: Double = 0.0 + override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false + override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) + } } fun tickExtractor(extractorNode: PowerNode.PowerExtractorNode): Future<*> = NewTransport.executor.submit { @@ -120,14 +125,14 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor val powerCheck = solarPanelNode.tickAndGetPower() if (powerCheck == 0) return@submit - val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) +// val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) // runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) } } // These methods are outside the class for speed -fun getPowerInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } +fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(world, NetworkType.POWER, origin) { true } /** * Runs the power transfer from the source to the destinations. pending rewrite diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt index f1e041afd3..23aaf3deb0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt @@ -4,16 +4,13 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.transport.cache.state.CacheState import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block -import org.bukkit.block.BlockFace abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network holder, works for now */) { private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() @@ -61,21 +58,4 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network } fun getRawCache() = cache - - fun getNextNodes(backwards: BlockFace, parentPos: BlockKey, parentType: CachedNode): Map { - val adjacent = ADJACENT_BLOCK_FACES.minus(backwards) - - val map = mutableMapOf() - - for (adjacentFace in adjacent) { - val pos = getRelative(parentPos, adjacentFace) - val cached = holder.getOrCacheGlobalNode(pos) ?: continue - - if (!cached.canTransferFrom(parentType, adjacentFace) || !parentType.canTransferTo(cached, adjacentFace)) continue - - map[adjacentFace] = cached - } - - return map - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt index 29529a38ce..6dfda20d31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt @@ -1,16 +1,11 @@ package net.horizonsend.ion.server.features.transport.node.manager -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidNodeFactory import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_TRANSPORT import org.bukkit.NamespacedKey import java.util.concurrent.Future @@ -39,10 +34,10 @@ class FluidNodeManager(holder: NetworkHolder) : NodeManager val source = extractorNode.getSourcePool().filterNot { it.isFull() }.randomOrNull() ?: return@submit - val destinations: ObjectOpenHashSet = getFluidInputs(extractorNode) - destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) - - if (destinations.isEmpty()) return@submit +// val destinations: ObjectOpenHashSet = getFluidInputs(extractorNode) +// destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) +// +// if (destinations.isEmpty()) return@submit // val transferred = minOf(source.getPower(), check) // val notRemoved = source.storage.removePower(transferred) @@ -57,5 +52,3 @@ class FluidNodeManager(holder: NetworkHolder) : NodeManager // } } } - -fun getFluidInputs(origin: TransportNode) = getNetworkDestinations(origin) { it.isCalling() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt index ed38d2efe3..49abe97848 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt @@ -1,14 +1,11 @@ package net.horizonsend.ion.server.features.transport.node.type.power -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks -import net.horizonsend.ion.server.features.transport.cache.getPowerInputs import net.horizonsend.ion.server.features.transport.node.NodeType import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.debugAudience class PowerExtractorNode(override val manager: PowerNodeManager) : ExtractorNode(), PowerPathfindingNode, UnTransferableNode { override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE @@ -30,12 +27,6 @@ class PowerExtractorNode(override val manager: PowerNodeManager) : ExtractorNode fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } - override fun toString(): String { - val destinations = getPowerInputs(this) - debugAudience.highlightBlocks(destinations.map { it.getCenter() }, 30L) - return "Extractor. found, can trasnsfer: ${getTransferAmount()}, numDestinations ${destinations.size}" - } - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable override fun loadIntoNetwork() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt index baccb9c1d3..ed10fadcb2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt @@ -1,36 +1,78 @@ package net.horizonsend.ion.server.features.transport.node.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.transport.cache.CachedNode -import net.horizonsend.ion.server.features.transport.node.TransportNode import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.kyori.adventure.audience.Audience import org.bukkit.World import org.bukkit.block.BlockFace import java.util.PriorityQueue import kotlin.math.roundToInt -inline fun getNetworkDestinations(origin: TransportNode, check: (T) -> Boolean): ObjectOpenHashSet { - val visitQueue = ArrayDeque() - val visitedSet = ObjectOpenHashSet() - val destinations = ObjectOpenHashSet() +fun getOrCacheNode(type: NetworkType, world: World, pos: BlockKey): CachedNode? { + val chunk = IonChunk[world, getX(pos).shr(4), getZ(pos).shr(4)] ?: return null + return type.get(chunk).getOrCache(pos) +} + +fun getNextNodes(networkType: NetworkType, world: World, backwards: BlockFace, parentPos: BlockKey, parentType: CachedNode): Map { + val adjacent = ADJACENT_BLOCK_FACES.minus(backwards) + + val map = mutableMapOf() + + for (adjacentFace in adjacent) { + val pos = getRelative(parentPos, adjacentFace) + val cached = getOrCacheNode(networkType, world, pos) ?: continue + + if (!cached.canTransferFrom(parentType, adjacentFace) || !parentType.canTransferTo(cached, adjacentFace)) continue + + map[adjacentFace] = cached + } - visitQueue.addAll(origin.cachedTransferable) + return map +} + +inline fun getNetworkDestinations(world: World, networkType: NetworkType, originPos: BlockKey, check: (T) -> Boolean): LongOpenHashSet { + val originNode = getOrCacheNode(networkType, world, originPos) ?: return LongOpenHashSet() + + val visitQueue = ArrayDeque>() + val visitedSet = LongOpenHashSet() + val destinations = LongOpenHashSet() + + val immediate = getNextNodes( + networkType = networkType, + world = world, + backwards = BlockFace.SELF, + parentPos = originPos, + parentType = originNode + ) + + visitQueue.addAll(immediate.map { Triple(it.key, getRelative(originPos, it.key), it.value) }) while (visitQueue.isNotEmpty()) { - val currentNode = visitQueue.removeFirst() - visitedSet.add(currentNode) + val (offset, currentPos, currentNode) = visitQueue.removeFirst() + visitedSet.add(currentPos) if (currentNode is T && check(currentNode)) { - destinations.add(currentNode) + destinations.add(currentPos) } - visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) + val next = getNextNodes( + networkType = networkType, + world = world, + backwards = offset.oppositeFace, + parentPos = currentPos, + parentType = currentNode + ).filterNot { visitedSet.contains(getRelative(currentPos, it.key)) }.map { Triple(it.key, getRelative(originPos, it.key), it.value) } + + visitQueue.addAll(next) } return destinations @@ -43,16 +85,16 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. - val queueSet = IntOpenHashSet() + val queueSet = LongOpenHashSet() fun queueAdd(wrapper: PathfindingNodeWrapper) { queue.add(wrapper) - queueSet.add(wrapper.node.hashCode()) + queueSet.add(wrapper.pos) } fun queueRemove(wrapper: PathfindingNodeWrapper) { queue.remove(wrapper) - queueSet.remove(wrapper.node.hashCode()) + queueSet.remove(wrapper.pos) } queueAdd(PathfindingNodeWrapper( @@ -84,7 +126,7 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: if (visited.contains(neighbor.node.hashCode())) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) - if (queueSet.contains(neighbor.node.hashCode())) { + if (queueSet.contains(neighbor.pos)) { val existingNeighbor = queue.first { it.node === neighbor.node } if (neighbor.g < existingNeighbor.g) { existingNeighbor.g = neighbor.g @@ -100,8 +142,16 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: } // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution -fun getNeighbors(current: PathfindingNodeWrapper): Array { - val transferable = current.network?.getNextNodes(current.offset, current.pos, current.node)?.toList() ?: return arrayOf() +fun getNeighbors(current: PathfindingNodeWrapper, audience: Audience? = null): Array { + val transferable = getNextNodes( + current.type, + current.world, + backwards = current.offset.oppositeFace, + parentPos = current.pos, + parentType = current.node + ).toList() + + audience?.information("${transferable.size} transferable nodes") return Array(transferable.size) { val (neighborFace, neighborType) = transferable[it] From 4a0ed6c0531301e5b3483417fe9da8c0b4ef2f39 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 10 Nov 2024 20:41:09 -0600 Subject: [PATCH 267/500] Remove old transport nodes --- .../server/command/admin/IonChunkCommand.kt | 102 +++---- .../modular/display/FlowMeterDisplay.kt | 6 +- .../custom/items/misc/MultimeterItem.kt | 16 +- .../entity/type/fluids/FluidStoringEntity.kt | 17 -- .../manager/ChunkMultiblockManager.kt | 3 +- .../multiblock/manager/MultiblockManager.kt | 3 +- .../manager/ShipMultiblockManager.kt | 3 +- .../ion/server/features/starship/Starship.kt | 2 +- .../server/features/transport/NewTransport.kt | 2 +- .../transport/cache/FluidTransportCache.kt | 4 +- .../transport/cache/PowerTransportCache.kt | 39 ++- .../transport/cache/TransportCache.kt | 4 +- .../manager/ChunkTransportManager.kt | 8 +- .../manager/ShipTransportManager.kt | 6 +- .../{node => }/manager/TransportManager.kt | 6 +- .../extractors/ChunkExtractorManager.kt | 4 +- .../manager/extractors/ExtractorManager.kt | 2 +- .../extractors/ShipExtractorManager.kt | 2 +- .../manager/holders/ChunkNetworkHolder.kt | 6 +- .../manager/holders/NetworkHolder.kt | 4 +- .../manager/holders/ShipNetworkHolder.kt | 6 +- .../transport/node/NodeRelationship.kt | 29 -- .../features/transport/node/NodeType.kt | 58 ---- .../features/transport/node/RelationHolder.kt | 96 ------ .../features/transport/node/TransportNode.kt | 186 ------------ .../node/manager/FluidNodeManager.kt | 54 ---- .../transport/node/manager/NodeManager.kt | 90 ------ .../node/manager/PowerNodeManager.kt | 40 --- .../features/transport/node/type/MultiNode.kt | 151 ---------- .../transport/node/type/SingleNode.kt | 43 --- .../node/type/fluid/FluidDirectionalNode.kt | 62 ---- .../node/type/fluid/FluidExtractorNode.kt | 54 ---- .../node/type/fluid/FluidFilterNode.kt | 4 - .../node/type/fluid/FluidFlowMeter.kt | 31 -- .../node/type/fluid/FluidInputNode.kt | 70 ----- .../fluid/FluidInvertedDirectionalNode.kt | 39 --- .../node/type/fluid/FluidJunctionNode.kt | 26 -- .../node/type/fluid/FluidLinearNode.kt | 24 -- .../node/type/fluid/FluidNodeFactory.kt | 56 ---- .../node/type/fluid/FluidPathfindingNode.kt | 10 - .../node/type/fluid/FluidValveNode.kt | 4 - .../node/type/general/DirectionalNode.kt | 31 -- .../node/type/general/ExtractorNode.kt | 30 -- .../transport/node/type/general/FlowMeter.kt | 75 ----- .../node/type/general/JunctionNode.kt | 60 ---- .../transport/node/type/general/LinearNode.kt | 76 ----- .../node/type/general/UnTransferableNode.kt | 4 - .../transport/node/type/power/EndRodNode.kt | 25 -- .../node/type/power/PowerDirectionalNode.kt | 70 ----- .../node/type/power/PowerExtractorNode.kt | 42 --- .../node/type/power/PowerFlowMeter.kt | 50 ---- .../node/type/power/PowerInputNode.kt | 97 ------- .../power/PowerInvertedDirectionalNode.kt | 34 --- .../node/type/power/PowerNodeFactory.kt | 114 -------- .../node/type/power/PowerPathfindingNode.kt | 10 - .../node/type/power/SolarPanelNode.kt | 273 ------------------ .../transport/node/type/power/SpongeNode.kt | 26 -- .../transport/node/util/NodeFactory.kt | 73 ----- .../features/transport/node/util/NodeUtils.kt | 147 ---------- .../features/transport/util/NetworkType.kt | 41 +++ .../{node => }/util/NodePathfinding.kt | 8 +- .../server/features/world/chunk/IonChunk.kt | 2 +- 62 files changed, 156 insertions(+), 2504 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/ChunkTransportManager.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/ShipTransportManager.kt (79%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/TransportManager.kt (61%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/extractors/ChunkExtractorManager.kt (89%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/extractors/ExtractorManager.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/extractors/ShipExtractorManager.kt (92%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/holders/ChunkNetworkHolder.kt (87%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/holders/NetworkHolder.kt (85%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/manager/holders/ShipNetworkHolder.kt (85%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{node => }/util/NodePathfinding.kt (98%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index f71be72a2f..816eb65fb5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,22 +4,14 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerPathfindingNode -import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text @@ -93,11 +85,11 @@ object IonChunkCommand : SLCommand() { sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") when (grid) { - is PowerNodeManager -> { - sender.information("${grid.solarPanels.size} solar panels") - sender.information("${grid.extractors.size} extractors") - sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") - } +// is PowerNodeManager -> { +// sender.information("${grid.solarPanels.size} solar panels") +// sender.information("${grid.extractors.size} extractors") +// sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") +// } } } @@ -143,50 +135,50 @@ object IonChunkCommand : SLCommand() { fun onTestPathfinding(sender: Player) { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() - val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") - val transferable = at.getTransferableNodes() - - fun getNext(node: TransportNode): Collection { - at as PowerPathfindingNode - return at.getNextNodes(node, null) - } - - sender.information("Transferable nodes from ${at.javaClass.simpleName}") - sender.information(transferable.joinToString(separator = "\n") { next -> - "${next.javaClass.simpleName} -> [${getNext(next).joinToString { it.javaClass.simpleName }}]" - }) +// val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager +// val key = toBlockKey(targeted.x, targeted.y, targeted.z) +// +// val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") +// val transferable = at.getTransferableNodes() + +// fun getNext(node: TransportNode): Collection { +// at as PowerPathfindingNode +// return at.getNextNodes(node, null) +// } +// +// sender.information("Transferable nodes from ${at.javaClass.simpleName}") +// sender.information(transferable.joinToString(separator = "\n") { next -> +// "${next.javaClass.simpleName} -> [${getNext(next).joinToString { it.javaClass.simpleName }}]" +// }) } @Subcommand("test flood") fun onTestFloodFill(sender: Player) { - val targeted = sender.getTargetBlock(null, 10) - val ionChunk = targeted.chunk.ion() - val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") - - val visitQueue = ArrayDeque() - val visitedSet = ObjectOpenHashSet() - val destinations = ObjectOpenHashSet() - - visitQueue.addAll(at.cachedTransferable) - var iterations = 0L - - while (visitQueue.isNotEmpty()) { - iterations++ - val currentNode = visitQueue.removeFirst() - Tasks.syncDelay(iterations) { sender.highlightBlock(currentNode.getCenter(), 5L) } - visitedSet.add(currentNode) - - if (currentNode is PowerInputNode) { - destinations.add(currentNode) - } - - visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) - } +// val targeted = sender.getTargetBlock(null, 10) +// val ionChunk = targeted.chunk.ion() +// val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager +// val key = toBlockKey(targeted.x, targeted.y, targeted.z) +// +// val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") +// +// val visitQueue = ArrayDeque() +// val visitedSet = ObjectOpenHashSet() +// val destinations = ObjectOpenHashSet() +// +// visitQueue.addAll(at.cachedTransferable) +// var iterations = 0L +// +// while (visitQueue.isNotEmpty()) { +// iterations++ +// val currentNode = visitQueue.removeFirst() +// Tasks.syncDelay(iterations) { sender.highlightBlock(currentNode.getCenter(), 5L) } +// visitedSet.add(currentNode) +// +// if (currentNode is PowerInputNode) { +// destinations.add(currentNode) +// } +// +// visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) +// } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index d809cb1220..5c10b72ffc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.client.display.modular.display -import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache import net.kyori.adventure.text.Component class FlowMeterDisplay( - private val meter: FlowMeter, + private val meter: PowerTransportCache.PowerNode.PowerFlowMeter, offsetLeft: Double, offsetUp: Double, offsetBack: Double, @@ -14,6 +14,6 @@ class FlowMeterDisplay( override fun deRegister() {} override fun getText(): Component { - return meter.formatFlow() + return Component.text("0") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 3049faa7e4..e89dccdd7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -8,11 +8,11 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.transport.cache.CachedNode -import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.features.transport.node.util.PathfindingNodeWrapper -import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.node.util.getHeuristic -import net.horizonsend.ion.server.features.transport.node.util.getNeighbors +import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.PathfindingNodeWrapper +import net.horizonsend.ion.server.features.transport.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.util.getHeuristic +import net.horizonsend.ion.server.features.transport.util.getNeighbors import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_VARIANT @@ -127,7 +127,8 @@ object MultimeterItem : CustomItem("Multimeter") { queueSet.remove(wrapper.node.hashCode()) } - queueAdd(PathfindingNodeWrapper( + queueAdd( + PathfindingNodeWrapper( world = world, pos = fromPos, node = fromNode, @@ -136,7 +137,8 @@ object MultimeterItem : CustomItem("Multimeter") { type = type, g = 0, f = 0 - )) + ) + ) val visited = LongOpenHashSet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index f99e4fa8e2..b69f886cca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -5,11 +5,9 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.kyori.adventure.text.Component import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext @@ -110,19 +108,4 @@ interface FluidStoringEntity { forward = fluidInputOffset.z ) } - - fun getFluidInputNode(): net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode? { - this as MultiblockEntity - val block = getFluidInputLocation() - - val chunk = IonChunk[world, block.x.shr(4), block.z.shr(4)] ?: return null - val manager = chunk.transportNetwork.powerNodeManager - val node = manager.getInternalNode(toBlockKey(block)) - - if (node != null) return node as? net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode - - // Try to place unregistered node - manager.manager.processBlockChange(world.getBlockAt(block.x, block.y, block.z)) - return manager.getInternalNode(toBlockKey(block)) as? net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 9b17941ed3..e4a6ba916a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -6,8 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index d29b8dba44..e9d9ebbad7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -8,8 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 2ceac31eb4..f298300d69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -13,8 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index 9c3c5cea1f..d9004b9e1e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -62,8 +62,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.thruster.ThrustDat import net.horizonsend.ion.server.features.starship.subsystem.thruster.ThrusterSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.WeaponSubsystem +import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.CustomTurretSubsystem -import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index abf8f05552..d4c2f523a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.transport.node.manager.TransportManager +import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt index 21f2ea76ea..9eb525d10e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.cache -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.util.NetworkType class FluidTransportCache(holder: NetworkHolder): TransportCache(holder) { override val type: NetworkType = NetworkType.FLUID diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt index 185b841f77..8cfb7ee6ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt @@ -1,14 +1,13 @@ package net.horizonsend.ion.server.features.transport.cache import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.node.util.getIdealPath -import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache.PowerNode.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache.PowerNode.PowerInputNode +import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.util.getIdealPath +import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -36,7 +35,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) - .addDataHandler(OBSERVER) { PowerNode.PowerFlowMeter(it.facing) } + .addDataHandler(OBSERVER) { PowerFlowMeter(it.facing) } .build() sealed interface PowerNode : CachedNode { @@ -86,6 +85,10 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor data class PowerFlowMeter(val face: BlockFace) : PowerNode { //TODO display + fun onCompleteChain(transferred: Int) { + + } + override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true @@ -97,6 +100,10 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) + + fun distributePower(toSend: Int): Int { + return 0 + } } } @@ -120,19 +127,11 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor // source.powerStorage.addPower(remainder) // } } - - private fun tickSolarPanel(solarPanelNode: SolarPanelNode) = NewTransport.executor.submit { - val powerCheck = solarPanelNode.tickAndGetPower() - if (powerCheck == 0) return@submit - -// val destinations: ObjectOpenHashSet = getPowerInputs(solarPanelNode) -// runPowerTransfer(solarPanelNode, destinations.toMutableList(), powerCheck) - } } // These methods are outside the class for speed -fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(world, NetworkType.POWER, origin) { true } +fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(world, NetworkType.POWER, origin) { true } /** * Runs the power transfer from the source to the destinations. pending rewrite @@ -143,7 +142,7 @@ private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: Cach val numDestinations = destinations.size val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(world, NetworkType.POWER, sourceType, sourcePos, destinations[it].position) + getIdealPath(world, NetworkType.POWER, sourceType, sourcePos, destinations[it].pos) }.getOrNull() } var maximumResistance: Double = -1.0 @@ -201,7 +200,7 @@ private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: Cach } private fun getRemainingCapacity(destination: PowerInputNode): Int { - return destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } + return 0 // destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } } private fun completeChain(path: Array?, transferred: Int) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt index 23aaf3deb0..8b11ae4362 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt @@ -2,8 +2,8 @@ package net.horizonsend.ion.server.features.transport.cache import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.transport.cache.state.CacheState -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.util.NetworkType +import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index a9952a0c08..c7db98b038 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.transport.node.manager +package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ChunkExtractorManager -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.holders.ChunkNetworkHolder import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt similarity index 79% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 56ed1f0d3a..0f1727d864 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -1,12 +1,12 @@ -package net.horizonsend.ion.server.features.transport.node.manager +package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ShipExtractorManager -import net.horizonsend.ion.server.features.transport.node.manager.holders.ShipNetworkHolder +import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager +import net.horizonsend.ion.server.features.transport.manager.holders.ShipNetworkHolder class ShipTransportManager(val starship: Starship) : TransportManager() { override val extractorManager: ShipExtractorManager = ShipExtractorManager(starship) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt similarity index 61% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 14c5bd834b..d7af7d24ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.node.manager +package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder abstract class TransportManager { abstract val extractorManager: ExtractorManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt similarity index 89% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index fe8b0b6d9a..96ecb8d32b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.transport.node.manager.extractors +package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index e1ec6c3dde..93559e1ed3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.manager.extractors +package net.horizonsend.ion.server.features.transport.manager.extractors import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt similarity index 92% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index f5318eb4e8..4b4457d55d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.manager.extractors +package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.starship.Starship diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt similarity index 87% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt index b02981f99a..227d6c4eaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.transport.node.manager.holders +package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt index a490577f62..1782ad7d57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.node.manager.holders +package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt index 816ab15416..ac5126c4d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.transport.node.manager.holders +package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.cache.CachedNode import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.manager.ShipTransportManager -import net.horizonsend.ion.server.features.transport.node.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt deleted file mode 100644 index 27d522ba9c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeRelationship.kt +++ /dev/null @@ -1,29 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.block.BlockFace - -/** - * This class represents a relationship between two nodes - * The information contains whether they may transfer to / from each other, from each side - **/ -data class NodeRelationship( - val position: BlockKey, - val otherPosition: BlockKey, - val holder: TransportNode, - val other: TransportNode, - val offset: BlockFace, - val canTransfer: Boolean -) { - /** - * Break the relation between the two nodes - **/ - fun breakUp() { - holder.relationHolder.raw()[position]?.remove(this) - other.relationHolder.raw()[otherPosition]?.remove(this) - holder.refreshTransferCache() - other.refreshTransferCache() - } -} - - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt deleted file mode 100644 index 19a5dff6cb..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/NodeType.kt +++ /dev/null @@ -1,58 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidDirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidFlowMeter -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInputNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidInvertedDirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidJunctionNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidLinearNode -import net.horizonsend.ion.server.features.transport.node.type.power.EndRodNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInvertedDirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.node.type.power.SpongeNode - -enum class NodeType(val clazz: Class) { - //POWER - SPONGE_NODE(SpongeNode::class.java), - END_ROD_NODE(EndRodNode::class.java), - SOLAR_PANEL_NODE(SolarPanelNode::class.java), - POWER_EXTRACTOR_NODE(PowerExtractorNode::class.java), - POWER_INPUT_NODE(PowerInputNode::class.java), - POWER_FLOW_METER(PowerFlowMeter::class.java), - POWER_DIRECTIONAL_NODE(PowerDirectionalNode::class.java), - POWER_INVERSE_DIRECTIONAL_NODE(PowerInvertedDirectionalNode::class.java), - - //FLUID - FLUID_INPUT(FluidInputNode::class.java), - FLUID_EXTRACTOR_NODE(FluidExtractorNode::class.java), - FLUID_JUNCTION(FluidJunctionNode::class.java), - LIGHTNING_ROD(FluidLinearNode::class.java), - FLUID_FLOW_METER(FluidFlowMeter::class.java), - FLUID_INVERTED_DIRECTIONAL_NODE(FluidInvertedDirectionalNode::class.java), - FLUID_DIRECTIONAL_NODE(FluidDirectionalNode::class.java), - - //ITEM - ; - - fun newInstance(network: NodeManager<*>): TransportNode { - return clazz.getDeclaredConstructor(network::class.java).newInstance(network) - } - - fun newInstance(): TransportNode { - return clazz.getDeclaredConstructor().newInstance() - } - - companion object { - val type = EnumDataType(NodeType::class.java) - private val byNode: Map, NodeType> = entries.associateBy { it.clazz } - - operator fun get(node: TransportNode): NodeType = byNode[node.javaClass] ?: throw NoSuchElementException("Unregistered node type ${node.javaClass.simpleName}!") - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt deleted file mode 100644 index f91b936b8e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/RelationHolder.kt +++ /dev/null @@ -1,96 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -import it.unimi.dsi.fastutil.ints.IntOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.block.BlockFace -import java.util.concurrent.BlockingDeque -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.LinkedBlockingDeque - -class RelationHolder(val node: TransportNode) { - private val relationships = ConcurrentHashMap>() - private val containsCache = ConcurrentHashMap() - - /** - * Create a relationship between this node and the provided node - * - * If neither side can transfer, a relation will not be created - **/ - fun addRelationship(other: TransportNode, holderPosition: BlockKey, otherPosition: BlockKey, nodeTwoOffset: BlockFace) { - // Do not add duplicates - val existingAt = relationships[holderPosition] - if (existingAt != null && existingAt.any { it.other == other }) return - - create(other, holderPosition, otherPosition, nodeTwoOffset) - other.neighborChanged(node) - } - - /** - * @param other The node this relation is being created with - * @param holderPosition The position that this node was created from - * @param otherPosition The position that the other node was found at - * @param nodeTwoOffset The direction that the other node was found - **/ - private fun create(other: TransportNode, holderPosition: BlockKey, otherPosition: BlockKey, nodeTwoOffset: BlockFace) { - val holderToOther = node.isTransferableTo(other) - val otherToHolder = other.isTransferableTo(node) - - // Add relation from this node to the other - add(holderPosition, NodeRelationship(holderPosition, otherPosition, node, other, nodeTwoOffset, holderToOther)) - // Add relation from the other to this - other.relationHolder.add(otherPosition, NodeRelationship(otherPosition, holderPosition, other, node, nodeTwoOffset.oppositeFace, otherToHolder)) - - node.refreshTransferCache() - other.refreshTransferCache() - } - - fun add(point: BlockKey, relation: NodeRelationship) { - relationships.getOrPut(point) { LinkedBlockingDeque() }.add(relation) - containsCache.getOrPut(point) { IntOpenHashSet() }.add(relation.other.hashCode()) - } - - fun remove(point: BlockKey, relation: NodeRelationship) { - relationships[point]?.remove(relation) - containsCache[point]?.remove(relation.other.hashCode()) - } - - fun removeAll(point: BlockKey): BlockingDeque? { - return relationships.remove(point) - } - - fun clear() { - relationships.values.forEach { - for (nodeRelationship in it) { - nodeRelationship.breakUp() - } - } - } - - fun removeRelationship(other: TransportNode) { - // Handle duplicate cases - for (key in relationships.keys.filter { containsCache.contains(other.hashCode()) }) { - relationships[key]?.removeAll { it.other == other } - } - - // Notify of neighbor change - other.neighborChanged(node) - } - - fun getAllOthers(): Set { - val others = ObjectOpenHashSet() - - for (key in relationships.keys) { - for (relation in relationships[key]!!) { - others.add(relation) - } - } - - return others - } - - fun raw() = relationships - - fun hasRelationAt(position: BlockKey): Boolean = relationships.containsKey(position) - fun hasRelationAtWith(point: BlockKey, other: TransportNode): Boolean = containsCache[point]?.contains(other.hashCode()) ?: false -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt deleted file mode 100644 index 0924a9bee0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/TransportNode.kt +++ /dev/null @@ -1,186 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node - -import kotlinx.serialization.SerializationException -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -/** - * Represents a single node, or step, in transport transportNetwork - **/ -abstract class TransportNode : PDCSerializable { - var isDead: Boolean = false - abstract val manager: NodeManager<*> - override val persistentDataType: Companion get() = Companion - abstract val type: NodeType - - val relationHolder = RelationHolder(this) - - /** - * Break all relations between this node and others - **/ - fun clearRelations() = relationHolder.clear() - - fun removeRelationship(other: TransportNode) = relationHolder.removeRelationship(other) - - fun removeRelationships(at: BlockKey) = relationHolder.removeAll(at) - - fun addRelationship(other: TransportNode, holderPosition: BlockKey, otherPosition: BlockKey, nodeTwoOffset: BlockFace) = - relationHolder.addRelationship(other, holderPosition, otherPosition, nodeTwoOffset) - - /** - * Returns whether this node may transport to the provided node - **/ - abstract fun isTransferableTo(node: TransportNode): Boolean - - /** - * - **/ - var cachedTransferable: ArrayDeque = ArrayDeque(getTransferableNodes()) - - fun refreshTransferCache() { - cachedTransferable = ArrayDeque(getTransferableNodes()) - relationCache.clear() - } - - /** - * Gets the distinct nodes this can transfer to - **/ - fun getTransferableNodes(): Collection { - return relationHolder.getAllOthers().mapNotNullTo(mutableSetOf()) { relation -> - // The other side of the relation, only if transfer is possible between this node and it. Double check if it is dead as well - relation.other.takeIf { relation.canTransfer && !it.isDead } - } - } - - /** - * Store additional required data in the serialized container - **/ - abstract fun storeData(persistentDataContainer: PersistentDataContainer) - - /** - * Load required data from the serialized container - **/ - abstract fun loadData(persistentDataContainer: PersistentDataContainer) - - /** - * Handle placement into the network upon loading, after data has been loaded - **/ - abstract fun loadIntoNetwork() - - /** - * Logic for handling the removal of this node - * - * Cleanup, splitting into multiple, etc - **/ - open fun handlePositionRemoval(position: BlockKey) {} - - /** - * The directions in which to try ro build relations - **/ - protected open val relationOffsets = ADJACENT_BLOCK_FACES - - /** - * Builds relations between this node and transferrable nodes - **/ - open fun buildRelations(position: BlockKey) { - for (offset in relationOffsets) { - val offsetKey = getRelative(position, offset, 1) - val neighborNode = manager.getNode(offsetKey) ?: continue - - if (this == neighborNode) continue - - // Add a relationship, if one should be added - addRelationship(neighborNode, position, offsetKey, offset) - } - } - - /** - * Notify a node if a neighbor changed - **/ - open fun neighborChanged(neighbor: TransportNode) {} - - /** - * Additional logic to be run once the node is placed - **/ - open fun onPlace(position: BlockKey) {} - - /** - * - **/ - abstract fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int - - private val relationCache = mutableMapOf>() - - fun getRelationshipWith(other: TransportNode): Map { - return relationCache.getOrPut(other) { - val cache = mutableMapOf() - for ((key, relations) in relationHolder.raw()) { - if (!relationHolder.hasRelationAtWith(key, other)) continue - cache[key] = relations.firstOrNull { it.other == other } ?: continue - } - - cache - } - } - - /** - * Get the center of this node, for display and pathfinding. - **/ - abstract fun getCenter(): Vec3i - - /** - * Get the distance between the nodes by using their relative center. - **/ - fun getDistance(previous: TransportNode): Double { - return previous.getCenter().distance(getCenter()) - } - - // - companion object : PersistentDataType { - override fun getPrimitiveType() = PersistentDataContainer::class.java - override fun getComplexType() = TransportNode::class.java - - override fun toPrimitive(complex: TransportNode, context: PersistentDataAdapterContext): PersistentDataContainer { - val pdc = context.newPersistentDataContainer() - pdc.set(NODE_TYPE, NodeType.type, complex.type) - - complex.storeData(pdc) - - return pdc - } - - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): TransportNode = try { - val type = primitive.get(NODE_TYPE, NodeType.type)!! - - val instance = type.newInstance() - - instance.loadData(primitive) - - instance - } catch (e: Throwable) { - throw SerializationException("Error deserializing multiblock data!", e) - } - - fun load(primitive: PersistentDataContainer, network: NodeManager<*>): TransportNode = try { - val type = primitive.get(NODE_TYPE, NodeType.type)!! - - val instance = type.newInstance(network) - - instance.loadData(primitive) - - instance - } catch (e: Throwable) { - throw SerializationException("Error deserializing multiblock data!", e) - } - } - // -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt deleted file mode 100644 index 6dfda20d31..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/FluidNodeManager.kt +++ /dev/null @@ -1,54 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.manager - -import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.fluid.FluidNodeFactory -import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_TRANSPORT -import org.bukkit.NamespacedKey -import java.util.concurrent.Future - -class FluidNodeManager(holder: NetworkHolder) : NodeManager(holder) { - override val namespacedKey: NamespacedKey = FLUID_TRANSPORT - override val type: NetworkType = NetworkType.FLUID - override val nodeFactory = FluidNodeFactory(this) - - override val dataVersion: Int = 0 - - override fun clearData() { - nodes.clear() - extractors.clear() - } - - fun tickTransport() { - extractors.values.forEach(::tickExtractor) - } - - private fun tickExtractor(extractorNode: FluidExtractorNode): Future<*> = NewTransport.executor.submit { - val transferCheck = extractorNode.getTransferAmount() - if (transferCheck == 0) return@submit - - extractorNode.markTicked() - - val source = extractorNode.getSourcePool().filterNot { it.isFull() }.randomOrNull() ?: return@submit - -// val destinations: ObjectOpenHashSet = getFluidInputs(extractorNode) -// destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) -// -// if (destinations.isEmpty()) return@submit - -// val transferred = minOf(source.getPower(), check) -// val notRemoved = source.storage.removePower(transferred) -// val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) -// -// if (transferred == remainder) { -// //TODO skip growing number of ticks if nothing to do -// } -// -// if (remainder > 0) { -// source.storage.addPower(remainder) -// } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt deleted file mode 100644 index 3b89f7156d..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/NodeManager.kt +++ /dev/null @@ -1,90 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.manager - -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode -import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.features.transport.node.util.NodeFactory -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import org.bukkit.NamespacedKey -import org.bukkit.block.Block -import org.bukkit.block.data.BlockData -import org.bukkit.persistence.PersistentDataContainer -import java.util.concurrent.ConcurrentHashMap - -abstract class NodeManager(val holder: NetworkHolder<*>) { - val nodes: ConcurrentHashMap = ConcurrentHashMap() - val extractors: ConcurrentHashMap = ConcurrentHashMap() - - val world get() = holder.getWorld() - - abstract val namespacedKey: NamespacedKey - abstract val type: NetworkType - abstract val nodeFactory: NodeFactory<*> - abstract val dataVersion: Int - - var ready: Boolean = false - - /** - * Handle the creation / loading of the node into memory - **/ - fun createNodeFromBlock(block: Block): Boolean { - val key = toBlockKey(block.x, block.y, block.z) - - return nodeFactory.create(key, block.blockData) - } - - fun createNodeFromBlock(position: BlockKey, data: BlockData): Boolean { - return nodeFactory.create(position, data) - } - - /** - * Save additional metadata into the network PDC - **/ - open fun saveAdditional(pdc: PersistentDataContainer) {} - - abstract fun clearData() - - /** - * Logic for when the holding chunk is unloaded - **/ - fun onUnload() { - // Break cross chunk relations - Tasks.async { breakAllRelations() } - } - - /** - * Get the neighbors of a node - **/ - fun buildRelations() { - for ((key, node) in nodes) { - node.buildRelations(key) - } - } - - /** - * Handles any cleanup tasks at the end of loading - **/ - open fun finalizeNodes() {} - - private fun breakAllRelations() { - nodes.values.forEach { it.clearRelations() } - } - - fun getNode(x: Int, y: Int, z: Int, allowNeighborChunks: Boolean = true): TransportNode? { - val key = toBlockKey(x, y, z) - return getNode(key, allowNeighborChunks) - } - - /** - * Gets a node from this chunk, or a direct neighbor, if loaded - **/ - fun getNode(key: BlockKey, allowNeighborChunks: Boolean = true): TransportNode? { - return null - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt deleted file mode 100644 index 9c8f8239de..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/manager/PowerNodeManager.kt +++ /dev/null @@ -1,40 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.manager - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet -import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.node.type.power.PowerExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.node.type.power.PowerInputNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerNodeFactory -import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode -import net.horizonsend.ion.server.features.transport.node.util.NetworkType -import net.horizonsend.ion.server.features.transport.node.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.node.util.getIdealPath -import net.horizonsend.ion.server.features.transport.node.util.getNetworkDestinations -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.POWER_TRANSPORT -import org.bukkit.NamespacedKey -import java.util.concurrent.Future -import kotlin.math.roundToInt - -class PowerNodeManager(holder: NetworkHolder) : NodeManager(holder) { - override val type: NetworkType = NetworkType.POWER - override val namespacedKey: NamespacedKey = POWER_TRANSPORT - override val nodeFactory: PowerNodeFactory = PowerNodeFactory(this) - - /** Store solar panels for ticking */ - val solarPanels: ObjectOpenHashSet = ObjectOpenHashSet() - - override val dataVersion: Int = 0 //TODO 1 - - override fun clearData() { - nodes.clear() - solarPanels.clear() - extractors.clear() - } - - fun tickTransport() { - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt deleted file mode 100644 index 606d9f31e2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/MultiNode.kt +++ /dev/null @@ -1,151 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type - -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.holders.ChunkNetworkHolder -import net.horizonsend.ion.server.features.transport.node.util.separateNode -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.averageBy -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import java.util.concurrent.ConcurrentHashMap - -/** - * A transport node that may cover many blocks to avoid making unnecessary steps - **/ -abstract class MultiNode, Z: MultiNode> : TransportNode() { - /** The positions occupied by the node **/ - val positions: MutableSet = ConcurrentHashMap.newKeySet() - - /** - * Adds new a position to this node - **/ - fun addPosition(position: BlockKey): Self { - positions += position - manager.nodes[position] = this - - onPlace(position) - - storedCenter = calculateCenter() - - @Suppress("UNCHECKED_CAST") - return this as Self - } - - /** - * Adds multiple positions to this node - **/ - fun addPositions(newPositions: Iterable) { - for (position in newPositions) { - positions += position - manager.nodes[position] = this - - onPlace(position) - } - - storedCenter = calculateCenter() - } - - /** - * Drain all the positions and connections to the provided node - **/ - fun drainTo(new: Self) { - clearRelations() - new.clearRelations() - - new.addPositions(positions) - new.positions.forEach { new.buildRelations(it) } - } - - fun rebuildRelations() { - clearRelations() - - positions.forEach { - buildRelations(it) - } - } - - /** - * Handle the removal of a position. Slits the node if necessary - * - **/ - override fun handlePositionRemoval(position: BlockKey) { - // Remove the position from the network - manager.nodes.remove(position) - - // Remove the position from this node - positions.remove(position) - removeRelationships(position) - - if (separateNode(this)) { - positions.clear() - clearRelations() - } - - storedCenter = calculateCenter() - } - - override fun loadIntoNetwork() { - for (key in positions) { - manager.nodes[key] = this - } - - storedCenter = calculateCenter() - } - - /** - * Returns the directly adjacent positions to this position that this node contains - **/ - fun adjacentPositions(key: BlockKey): Set { - return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableSetOf()) { face -> - getRelative(key, face).takeIf { positions.contains(it) } - } - } - - /** - * Places the set of positions into the network as this type of node. - **/ - open fun ofPositions(positions: Set): Self { - @Suppress("UNCHECKED_CAST") - val newNode = type.newInstance(manager) as Self - - positions.forEach { - newNode.addPosition(it) - } - - newNode.rebuildRelations() - - return newNode - } - - abstract fun addBack(position: BlockKey) - - open val maxPositions: Int = 32 - - open fun canAdd(position: BlockKey): Boolean { - val holder = manager.holder as? ChunkNetworkHolder<*> - if (holder != null && - (getX(position).shr(4) != holder.manager.chunk.x || - getZ(position).shr(4) != holder.manager.chunk.z) - ) return false - - return positions.size < maxPositions - } - - var storedCenter: Vec3i = this.calculateCenter() - - fun calculateCenter(): Vec3i { - val xAvg = positions.averageBy { getX(it).toDouble() } - val yAvg = positions.averageBy { getY(it).toDouble() } - val zAvg = positions.averageBy { getZ(it).toDouble() } - - return Vec3i(xAvg.toInt(), yAvg.toInt(), zAvg.toInt()) - } - - override fun getCenter(): Vec3i { - return storedCenter - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt deleted file mode 100644 index 31ce47446c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/SingleNode.kt +++ /dev/null @@ -1,43 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type - -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates - -/** - * A node that only occupies a single block - **/ -abstract class SingleNode : TransportNode() { - var position by Delegates.notNull() - - override fun loadIntoNetwork() { - manager.nodes[position] = this - } - - override fun onPlace(position: BlockKey) { - buildRelations(position) - } - - override fun handlePositionRemoval(position: BlockKey) { - isDead = true - manager.nodes.remove(position) - clearRelations() - } - - override fun getCenter(): Vec3i { - return toVec3i(position) - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt deleted file mode 100644 index d1a777ef2e..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidDirectionalNode.kt +++ /dev/null @@ -1,62 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_DIRECTIONAL_NODE -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.horizonsend.ion.server.features.transport.node.type.power.PowerDirectionalNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Material -import org.bukkit.persistence.PersistentDataContainer -import kotlin.properties.Delegates - -class FluidDirectionalNode(override val manager: FluidNodeManager) : DirectionalNode(), FluidPathfindingNode { - override val type: NodeType = FLUID_DIRECTIONAL_NODE - private var variant: Material by Delegates.notNull() - - constructor(network: FluidNodeManager, position: BlockKey, variant: Material) : this(network) { - this.position = position - this.variant = variant - } - - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is UnTransferableNode) return false - return node !is FluidJunctionNode - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque { - if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) - - // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. - // So there will likely only be a single relation to this - val direction = previous.getRelationshipWith(this).values - if (direction.isEmpty()) return cachedTransferable - val face = direction.first().offset - - getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } - - return cachedTransferable - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - super.storeData(persistentDataContainer) - persistentDataContainer.set(NamespacedKeys.NODE_VARIANT, PowerDirectionalNode.materialDataType, variant) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - super.loadData(persistentDataContainer) - variant = persistentDataContainer.get(NamespacedKeys.NODE_VARIANT, PowerDirectionalNode.materialDataType)!! - } - - override fun canTransfer(resource: PipedFluid): Boolean { - return true - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt deleted file mode 100644 index e5ed162b3a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidExtractorNode.kt +++ /dev/null @@ -1,54 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_EXTRACTOR_NODE -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.toMap - -class FluidExtractorNode(override val manager: FluidNodeManager) : ExtractorNode(), FluidPathfindingNode, UnTransferableNode { - override val type: NodeType = FLUID_EXTRACTOR_NODE - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int = 0 - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque = cachedTransferable - - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is UnTransferableNode - } - - override fun loadIntoNetwork() { - super.loadIntoNetwork() - manager.extractors[position] = this - } - - override fun onPlace(position: BlockKey) { - super.onPlace(position) - manager.extractors[position] = this - } - - override fun canTransfer(resource: PipedFluid): Boolean { - return false - } - - fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? FluidInputNode }.flatMap { it.getEntities() } - - fun getAvailableFluidTypes(): List { - val sources = getSourcePool() - - val new = mutableListOf() - for (source in sources) { - for ((resource, _) in source.getStoredResources()) { - new.add(resource ?: continue) - } - } - - return new - } - - fun getAvailableFluids() = getSourcePool().flatMap { it.getStoredResources().entries }.toMap() -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt deleted file mode 100644 index a693762056..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFilterNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -class FluidFilterNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt deleted file mode 100644 index 1e8b498509..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidFlowMeter.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.kyori.adventure.text.Component - -class FluidFlowMeter(override val manager: FluidNodeManager) : FlowMeter(), FluidPathfindingNode { - override val type: NodeType = NodeType.FLUID_FLOW_METER - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque = cachedTransferable - - override fun formatFlow(): Component { - return Component.text("bbb") - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 0 - } - - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is UnTransferableNode - } - - override fun canTransfer(resource: PipedFluid): Boolean { - return true - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt deleted file mode 100644 index b4ed85633f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInputNode.kt +++ /dev/null @@ -1,70 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.multiblock.MultiblockEntities -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import net.horizonsend.ion.server.miscellaneous.utils.isWallSign -import org.bukkit.block.data.type.WallSign -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -class FluidInputNode(override val manager: FluidNodeManager) : SingleNode() { - override val type: NodeType = NodeType.FLUID_INPUT - - constructor(network: FluidNodeManager, position: BlockKey) : this(network) { - this.position = position - } - - override fun isTransferableTo(node: TransportNode): Boolean { - return false - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 0 - } - - fun getEntities(): Collection { - return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableListOf()) { - val relativeKey = getRelative(position, it) - val entity = MultiblockEntities.getMultiblockEntity(manager.world, relativeKey) as? FluidStoringEntity - if (entity != null) return@mapNotNullTo entity - - val data = getBlockDataSafe(manager.world, getX(relativeKey), getY(relativeKey), getZ(relativeKey)) ?: return@mapNotNullTo null - if (!data.material.isWallSign) return@mapNotNullTo null - data as WallSign - - val originKey = getRelative(relativeKey, data.facing.oppositeFace) - MultiblockEntities.getMultiblockEntity(manager.world, originKey) as? FluidStoringEntity - } - } - - fun canConsume(resource: PipedFluid) { - - } - - fun isCalling(): Boolean { - val entities = getEntities() - if (entities.isEmpty()) return false - return entities.any { !it.isFull() } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt deleted file mode 100644 index 73d7b0c36b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidInvertedDirectionalNode.kt +++ /dev/null @@ -1,39 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode - -class FluidInvertedDirectionalNode(override val manager: FluidNodeManager) : DirectionalNode(), FluidPathfindingNode { - override val type: NodeType = NodeType.FLUID_INVERTED_DIRECTIONAL_NODE - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque { - if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) - - // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. - // So there will likely only be a single relation to this - val direction = previous.getRelationshipWith(this).values - if (direction.isEmpty()) return cachedTransferable // just in case - val face = direction.first().offset - - getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } - - return cachedTransferable - } - - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is UnTransferableNode) return false - return node !is FluidLinearNode - } - - override fun canTransfer(resource: PipedFluid): Boolean { - return true - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt deleted file mode 100644 index 1d0edde16c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidJunctionNode.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i - -class FluidJunctionNode(network: FluidNodeManager) : JunctionNode(network) { - override val type: NodeType = NodeType.FLUID_JUNCTION - constructor(network: FluidNodeManager, origin: BlockKey) : this(network) { - positions.add(origin) - } - - override fun addBack(position: BlockKey) { - manager.nodeFactory.addJunctionNode(position, type, handleRelationships = false) - } - - override fun toString(): String { - return """ - [Gas Junction Node] - ${positions.size} positions - Relationships: ${relationHolder.raw().entries.joinToString { (key, relations) -> "[${toVec3i(key)} = (${relations.joinToString { it.other.toString() }}(]" }} - """.trimIndent() - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt deleted file mode 100644 index c2b3153202..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidLinearNode.kt +++ /dev/null @@ -1,24 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.NodeType.LIGHTNING_ROD -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import org.bukkit.block.data.Directional - -// Aka lightning rod -class FluidLinearNode(network: FluidNodeManager) : LinearNode(network) { - override val type: NodeType = LIGHTNING_ROD - - override fun addBack(position: BlockKey) { - val data = getBlockDataSafe(manager.world, getX(position), getY(position), getZ(position)) as? Directional ?: return - - manager.nodeFactory.addLinearNode(position, data.facing.axis, type, handleRelationships = false) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt deleted file mode 100644 index fec691ce71..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidNodeFactory.kt +++ /dev/null @@ -1,56 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_EXTRACTOR_NODE -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_FLOW_METER -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_INPUT -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_INVERTED_DIRECTIONAL_NODE -import net.horizonsend.ion.server.features.transport.node.NodeType.FLUID_JUNCTION -import net.horizonsend.ion.server.features.transport.node.NodeType.LIGHTNING_ROD -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.util.NodeFactory -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.isChiseledCopper -import net.horizonsend.ion.server.miscellaneous.utils.isCopperBlock -import net.horizonsend.ion.server.miscellaneous.utils.isCopperBulb -import org.bukkit.Material -import org.bukkit.Material.FLETCHING_TABLE -import org.bukkit.Material.IRON_BLOCK -import org.bukkit.Material.OBSERVER -import org.bukkit.Material.REDSTONE_BLOCK -import org.bukkit.block.data.BlockData -import org.bukkit.block.data.Directional - -class FluidNodeFactory(network: FluidNodeManager) : NodeFactory(network) { - override fun create(key: BlockKey, data: BlockData): Boolean { - if (network.nodes.contains(key)) return false - - when { - data.material == Material.LIGHTNING_ROD -> addLinearNode(key, (data as Directional).facing.axis, LIGHTNING_ROD) - data.material.isCopperBlock -> addJunctionNode(key, FLUID_JUNCTION) - - data.material == Material.CRAFTING_TABLE -> addSimpleSingleNode(key, FLUID_EXTRACTOR_NODE) - data.material == FLETCHING_TABLE -> addSimpleSingleNode(key, FLUID_INPUT) - - data.material == OBSERVER -> addDirectionalNode(key, (data as Directional).facing, FLUID_FLOW_METER) - - data.material == REDSTONE_BLOCK -> addMergeNode(key, REDSTONE_BLOCK) - data.material == IRON_BLOCK -> addMergeNode(key, IRON_BLOCK) - data.material == Material.LAPIS_BLOCK -> addSimpleSingleNode(key, FLUID_INVERTED_DIRECTIONAL_NODE) - - data.material.isChiseledCopper -> println("TODO") - - data.material.isCopperBulb -> println("TODO") - - else -> return false - } - - return true - } - - private fun addMergeNode(key: BlockKey, variant: Material) { - network.nodes[key] = FluidDirectionalNode(network, key, variant).apply { - onPlace(position) - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt deleted file mode 100644 index 6fca6140e0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidPathfindingNode.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.node.TransportNode - -interface FluidPathfindingNode { - fun getNextNodes(previous: TransportNode, destination: TransportNode?, resource: PipedFluid): ArrayDeque - - fun canTransfer(resource: PipedFluid): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt deleted file mode 100644 index 299ed0401d..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/fluid/FluidValveNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.fluid - -class FluidValveNode { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt deleted file mode 100644 index 978a6b702f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/DirectionalNode.kt +++ /dev/null @@ -1,31 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.general - -import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.AXIS -import org.bukkit.block.BlockFace -import org.bukkit.block.BlockFace.NORTH -import org.bukkit.persistence.PersistentDataContainer - -abstract class DirectionalNode : SingleNode() { - lateinit var direction: BlockFace - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - super.loadData(persistentDataContainer) - direction = persistentDataContainer.getOrDefault(AXIS, directionPDC, NORTH) - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - super.storeData(persistentDataContainer) - persistentDataContainer.set(AXIS, directionPDC, direction) - } - - companion object { - private val directionPDC = EnumDataType(BlockFace::class.java) - } - - fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { - it.offset == incoming.oppositeFace && it.canTransfer - }?.other -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt deleted file mode 100644 index 31d6431d7f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/ExtractorNode.kt +++ /dev/null @@ -1,30 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.general - -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import kotlin.math.roundToInt - -abstract class ExtractorNode : SingleNode() { - private var lastTicked: Long = System.currentTimeMillis() - - fun markTicked() { - lastTicked = System.currentTimeMillis() - } - - fun getTransferAmount(): Int { - val interval = IonServer.transportSettings.extractorTickIntervalMS.toDouble() - - return (IonServer.transportSettings.maxPowerRemovedPerExtractorTick * ((System.currentTimeMillis() - lastTicked) / interval)).roundToInt() - } - - override fun handlePositionRemoval(position: BlockKey) { - manager.extractors.remove(position) - super.handlePositionRemoval(position) - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 0 - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt deleted file mode 100644 index 4fc33a18cd..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/FlowMeter.kt +++ /dev/null @@ -1,75 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.general - -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.kyori.adventure.text.Component - -abstract class FlowMeter : DirectionalNode() { - private val STORED_AVERAGES = 20 - protected val averages = mutableListOf() - - abstract fun formatFlow(): Component - - fun onCompleteChain(transferred: Int) { - addTransferred(TransferredPower(transferred, System.currentTimeMillis())) - if (::displayHandler.isInitialized) displayHandler.update() - } - - private fun addTransferred(transferredSnapshot: TransferredPower) { - val currentSize = averages.size - - if (currentSize < STORED_AVERAGES) { - averages.add(transferredSnapshot) - return - } - - // If it is full, shift all averages to the right - for (index in 18 downTo 0) { - averages[index + 1] = averages[index] - } - - averages[0] = transferredSnapshot - } - - protected fun calculateAverage(): Double { - val sum = averages.sumOf { it.transferred } - - val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 - - return sum / timeDiff - } - - private lateinit var displayHandler: TextDisplayHandler - - private fun setupDisplayEntity() { - displayHandler = DisplayHandlers.newBlockOverlay( - manager.world, - toVec3i(position), - direction, - FlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) - ).register() - } - - override fun loadIntoNetwork() { - setupDisplayEntity() - - super.loadIntoNetwork() - } - - override fun onPlace(position: BlockKey) { - runCatching { setupDisplayEntity() } - - super.onPlace(position) - } - - override fun handlePositionRemoval(position: BlockKey) { - if (::displayHandler.isInitialized) displayHandler.remove() - - super.handlePositionRemoval(position) - } - - protected data class TransferredPower(val transferred: Int, val time: Long) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt deleted file mode 100644 index 9356db1cf4..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/JunctionNode.kt +++ /dev/null @@ -1,60 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.general - -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.averageBy -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import kotlin.math.roundToInt - -abstract class JunctionNode, A: JunctionNode, B: JunctionNode>(override val manager: T) : MultiNode() { - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is UnTransferableNode && node !is SolarPanelNode - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - if (previousNode != null) { - if (nextNode != null) { - // Provided both means it needs to be more precise for an accurate distribution of resources. Get in / out locations via relations - val relationPrevious = getRelationshipWith(previousNode) - val relationNext = getRelationshipWith(nextNode) - - val previousVec = Vec3i( - relationPrevious.keys.averageBy { getX(it).toDouble() }.roundToInt(), - relationPrevious.keys.averageBy { getY(it).toDouble() }.roundToInt(), - relationPrevious.keys.averageBy { getZ(it).toDouble() }.roundToInt() - ) - - val nextVec = Vec3i( - relationNext.keys.averageBy { getX(it).toDouble() }.roundToInt(), - relationNext.keys.averageBy { getY(it).toDouble() }.roundToInt(), - relationNext.keys.averageBy { getZ(it).toDouble() }.roundToInt() - ) - - return maxOf(1, previousVec.distance(nextVec).roundToInt()) - } - - // Rough distance - return getCenter().distance(previousNode.getCenter()).roundToInt() - } - - // As a fallback, shouldn't happen - return 0 - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt deleted file mode 100644 index 79a6b372c4..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/LinearNode.kt +++ /dev/null @@ -1,76 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.general - -import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.faces -import org.bukkit.Axis -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType -import kotlin.properties.Delegates - -abstract class LinearNode, A: LinearNode, B: LinearNode>(override val manager: T) : MultiNode() { - var axis by Delegates.notNull() - override val relationOffsets: Set get() = axis.faces.toList().toSet() - - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is UnTransferableNode) return false - - // This is probably very laggy - val endPoints = positions.flatMap { pos -> - axis.faces.toList().map { face -> getRelative(pos, face) } - }.filterNot { positions.contains(it) } - - when (node) { - is MultiNode<*, *> -> if (endPoints.none { node.positions.contains(it) }) return false - is SingleNode -> if (!endPoints.contains(node.position)) return false - } - - return node !is SolarPanelNode - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - - axis = persistentDataContainer.getOrDefault(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), Axis.Y) - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NamespacedKeys.NODE_COVERED_POSITIONS, PersistentDataType.LONG_ARRAY, positions.toLongArray()) - persistentDataContainer.set(NamespacedKeys.AXIS, EnumDataType(Axis::class.java), axis) - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return positions.size // Always in one end and out the other - } - - override fun ofPositions(positions: Set): B { - @Suppress("UNCHECKED_CAST") - val newNode = type.newInstance(manager) as B - - // Need to set the axis before the rebuild, hence the override - newNode.axis = axis - - positions.forEach { - newNode.addPosition(it) - newNode.buildRelations(it) - } - - return newNode - } - - fun setAxis(axis: Axis): LinearNode { - this.axis = axis - return this - } - - override fun toString(): String = "(END ROD NODE: Axis: $axis; ${positions.size} positions; ${relationHolder.getAllOthers().size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes)" -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt deleted file mode 100644 index 38303132f6..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/general/UnTransferableNode.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.general - -/** Marks a node as being unable to be transferred to by any other node */ -interface UnTransferableNode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt deleted file mode 100644 index 25391d56d7..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/EndRodNode.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import org.bukkit.block.data.Directional - -class EndRodNode(network: PowerNodeManager) : LinearNode(network), PowerPathfindingNode { - override val type: NodeType = NodeType.END_ROD_NODE - - override fun addBack(position: BlockKey) { - val data = getBlockDataSafe(manager.world, getX(position), getY(position), getZ(position)) as? Directional ?: return - - manager.nodeFactory.addLinearNode(position, data.facing.axis, type, handleRelationships = false) - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt deleted file mode 100644 index b6a583f72b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerDirectionalNode.kt +++ /dev/null @@ -1,70 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Material -import org.bukkit.block.BlockFace -import org.bukkit.persistence.PersistentDataContainer -import kotlin.properties.Delegates - -class PowerDirectionalNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { - override val type: NodeType = NodeType.POWER_DIRECTIONAL_NODE - private var variant: Material by Delegates.notNull() - - constructor(network: PowerNodeManager, position: BlockKey, variant: Material) : this(network) { - this.position = position - this.variant = variant - } - - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is UnTransferableNode) return false - if (node is SpongeNode) return false - return node !is SolarPanelNode - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - super.storeData(persistentDataContainer) - persistentDataContainer.set(NamespacedKeys.NODE_VARIANT, materialDataType, variant) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - super.loadData(persistentDataContainer) - variant = persistentDataContainer.get(NamespacedKeys.NODE_VARIANT, materialDataType)!! - } - - companion object { - val materialDataType = EnumDataType(Material::class.java) - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque { - if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) - - // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. - // So there will likely only be a single relation to this - val direction = previous.getRelationshipWith(this).values - if (direction.isEmpty()) return cachedTransferable - val face = direction.first().offset - - getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } - - return cachedTransferable - } - - fun getForwardTransferable(incoming: BlockFace): TransportNode? = relationHolder.getAllOthers().firstOrNull { - it.offset == incoming && it.canTransfer - }?.other - - override fun toString(): String { - return "${relationHolder.getAllOthers().size} relations, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }}" - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt deleted file mode 100644 index 49abe97848..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerExtractorNode.kt +++ /dev/null @@ -1,42 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.ExtractorNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey - -class PowerExtractorNode(override val manager: PowerNodeManager) : ExtractorNode(), PowerPathfindingNode, UnTransferableNode { - override val type: NodeType = NodeType.POWER_EXTRACTOR_NODE - - var tickNumber: Int = 0 - var tickInterval: Int = 1 - - /* - * The extractor node should be allowed to transfer into any regular node. - * - * Since it does only takes from inputs, it cannot transfer into them. - * - * And it cannot transfer into any other power source - */ - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is PowerInputNode) return false - return node !is PowerExtractorNode && node !is SolarPanelNode - } - - fun getSourcePool() = relationHolder.getAllOthers().mapNotNull { it.other as? PowerInputNode }.flatMap { it.getPoweredEntities() } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable - - override fun loadIntoNetwork() { - super.loadIntoNetwork() - manager.extractors[position] = this - } - - override fun onPlace(position: BlockKey) { - super.onPlace(position) - manager.extractors[position] = this - } -} - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt deleted file mode 100644 index d9f8bca307..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerFlowMeter.kt +++ /dev/null @@ -1,50 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth -import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY -import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.FlowMeter -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.newline -import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor.GREEN -import net.kyori.adventure.text.format.NamedTextColor.YELLOW - -class PowerFlowMeter(override val manager: PowerNodeManager) : FlowMeter(), PowerPathfindingNode { - override val type: NodeType = NodeType.POWER_FLOW_METER - - /* - * Should transfer power like any normal node. - * - * And it cannot transfer into a source - */ - override fun isTransferableTo(node: TransportNode): Boolean { - return node !is UnTransferableNode && node !is SolarPanelNode - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable - - companion object { - val firstLine = text("E: ", YELLOW) - val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Second", GREEN)) - } - - override fun formatFlow(): Component { - var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) - - // If no averages, or no power has been moved in 5 seconds, go to 0 - if (averages.isEmpty() || System.currentTimeMillis() - averages.maxOf { it.time } > 5000) { - avg = 0.0 - } - - return ofChildren(firstLine, text(avg, GREEN), secondLine) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt deleted file mode 100644 index 0de1cb7321..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInputNode.kt +++ /dev/null @@ -1,97 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.multiblock.MultiblockEntities -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import net.horizonsend.ion.server.miscellaneous.utils.isWallSign -import org.bukkit.block.data.type.WallSign -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -class PowerInputNode(override val manager: PowerNodeManager) : SingleNode(), PowerPathfindingNode { - override val type: NodeType = NodeType.POWER_INPUT_NODE - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, PersistentDataType.LONG, position) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - position = persistentDataContainer.get(NODE_COVERED_POSITIONS, PersistentDataType.LONG)!! - } - - fun isCalling(): Boolean { - val entities = getPoweredEntities() - if (entities.isEmpty()) return false - return entities.any { it.powerStorage.getRemainingCapacity() > 0 } - } - - fun getPoweredEntities(): Collection { - return ADJACENT_BLOCK_FACES.mapNotNullTo(mutableListOf()) { - val relativeKey = getRelative(position, it) - val entity = MultiblockEntities.getMultiblockEntity(manager.world, relativeKey) as? PoweredMultiblockEntity - if (entity != null) return@mapNotNullTo entity - - val data = getBlockDataSafe(manager.world, getX(relativeKey), getY(relativeKey), getZ(relativeKey)) ?: return@mapNotNullTo null - if (!data.material.isWallSign) return@mapNotNullTo null - data as WallSign - - val originKey = getRelative(relativeKey, data.facing.oppositeFace) - MultiblockEntities.getMultiblockEntity(manager.world, originKey) as? PoweredMultiblockEntity - } - } - - fun distributePower(power: Int): Int { - val entities = getPoweredEntities().filterTo(mutableListOf()) { !it.powerStorage.isFull() } - - if (entities.isEmpty()) return power - - // Skip math for most scenarios - if (entities.size == 1) return entities.first().powerStorage.addPower(power) - - var remainingPower = power - - while (remainingPower > 0) { - if (entities.isEmpty()) break - - val share = remainingPower / entities.size - val minRemaining = entities.minOf { it.powerStorage.getRemainingCapacity() } - val distributed = minOf(minRemaining, share) - - val iterator = entities.iterator() - while (iterator.hasNext()) { - val entity = iterator.next() - - val r = entity.powerStorage.addPower(distributed) - if (entity.powerStorage.isFull()) iterator.remove() - - remainingPower -= (distributed - r) - } - } - - return remainingPower - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 0 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque { - return ArrayDeque(0) // Can't transfer to anything - } - - override fun isTransferableTo(node: TransportNode): Boolean { - return false - } - - override fun toString(): String = "POWER INPUT NODE. Bound to ${getPoweredEntities().joinToString { it.toString() }}" -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt deleted file mode 100644 index 206d407468..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerInvertedDirectionalNode.kt +++ /dev/null @@ -1,34 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode - -class PowerInvertedDirectionalNode(override val manager: PowerNodeManager) : DirectionalNode(), PowerPathfindingNode { - override val type: NodeType = NodeType.POWER_INVERSE_DIRECTIONAL_NODE - - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is EndRodNode) return false - return node !is UnTransferableNode && node !is SolarPanelNode - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - return 1 - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque { - if (destination != null && relationHolder.hasRelationAtWith(position, destination)) return ArrayDeque(listOf(destination)) - - // Since this is a single node, and the previous node must be transferable to this, it can't be a sponge. - // So there will likely only be a single relation to this - val direction = previous.getRelationshipWith(this).values - if (direction.isEmpty()) return cachedTransferable // just in case - val face = direction.first().offset - - getForwardTransferable(face)?.let { return ArrayDeque(listOf(it)) } - - return cachedTransferable - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt deleted file mode 100644 index 00d497c8d9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerNodeFactory.kt +++ /dev/null @@ -1,114 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_EXTRACTOR_NODE -import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_FLOW_METER -import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_INPUT_NODE -import net.horizonsend.ion.server.features.transport.node.NodeType.POWER_INVERSE_DIRECTIONAL_NODE -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.power.SolarPanelNode.Companion.matchesSolarPanelStructure -import net.horizonsend.ion.server.features.transport.node.util.NodeFactory -import net.horizonsend.ion.server.features.transport.node.util.handleMerges -import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import org.bukkit.Material -import org.bukkit.block.BlockFace.DOWN -import org.bukkit.block.BlockFace.UP -import org.bukkit.block.data.BlockData -import org.bukkit.block.data.Directional - -class PowerNodeFactory(network: PowerNodeManager) : NodeFactory(network) { - override fun create(key: BlockKey, data: BlockData): Boolean { - if (network.nodes.contains(key)) return false - - when (data.material) { - Material.END_ROD -> addLinearNode(key, (data as Directional).facing.axis, NodeType.END_ROD_NODE) - Material.SPONGE -> addJunctionNode(key, NodeType.SPONGE_NODE) - - // If a solar panel is not created, add an extractor - Material.CRAFTING_TABLE -> if (!checkSolarPanels(key, 1)) addSimpleSingleNode(key, POWER_EXTRACTOR_NODE) - Material.DIAMOND_BLOCK -> checkSolarPanels(key, 1) - Material.DAYLIGHT_DETECTOR -> checkSolarPanels(key, 2) - - Material.NOTE_BLOCK -> addSimpleSingleNode(key, POWER_INPUT_NODE) - Material.OBSERVER -> addDirectionalNode(key, (data as Directional).facing, POWER_FLOW_METER) - - Material.IRON_BLOCK -> addMergeNode(key, Material.IRON_BLOCK) - Material.REDSTONE_BLOCK -> addMergeNode(key, Material.REDSTONE_BLOCK) - Material.LAPIS_BLOCK -> addSimpleSingleNode(key, POWER_INVERSE_DIRECTIONAL_NODE) - - // Redstone controlled gate - // block.type.isRedstoneLamp -> GateNode(this, x, y, z) - else -> return false - } - - return true - } - - /** - * Provided the key of the extractor, create or combine solar panel nodes - **/ - fun addSolarPanel(position: BlockKey, handleRelationships: Boolean = true) { - // The diamond and daylight detector - val diamondPosition = getRelative(position, UP, 1) - val detectorPosition = getRelative(position, UP, 2) - - // Get the nodes that might be touching the solar panel - // - // 2d cross-section for demonstration: C is the origin crafting table, X are positions checked - // - // X X - // X X - // X C X - // X X - - // If another solar panel is found at any of those positions, handle merges - val neighboringNodes = CARDINAL_BLOCK_FACES.mapNotNullTo(mutableListOf()) { direction -> - val relativeSide = getRelative(position, direction) - - (-1..3).firstNotNullOfOrNull { - val neighborKey = getRelative(relativeSide, UP, it) - val node = network.nodes[neighborKey] - if (node !is SolarPanelNode) return@firstNotNullOfOrNull null - - // Take only extractor locations - node.takeIf { node.isIntact(network.world, neighborKey) } - } - } - - val node = when (neighboringNodes.size) { - 0 -> SolarPanelNode(network).apply { - manager.solarPanels += this - }.addPosition(position, diamondPosition, detectorPosition) - - 1 -> neighboringNodes.firstOrNull()?.addPosition(position, diamondPosition, detectorPosition) ?: throw ConcurrentModificationException("Node removed during processing") - - in 2..4 -> handleMerges(neighboringNodes).addPosition(position, diamondPosition, detectorPosition) - - else -> throw IllegalArgumentException() - } - - if (handleRelationships) node.rebuildRelations() - } - - private fun addMergeNode(key: BlockKey, variant: Material) { - network.nodes[key] = PowerDirectionalNode(network, key, variant).apply { - onPlace(position) - } - } - - private fun checkSolarPanels(position: BlockKey, extractorDistance: Int): Boolean { - val extractorKey = getRelative(position, DOWN, extractorDistance) - - val check = matchesSolarPanelStructure(network.world, extractorKey) - - if (check) { - network.nodes.remove(extractorKey) - addSolarPanel(extractorKey) - } - - return check - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt deleted file mode 100644 index 59167601c2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/PowerPathfindingNode.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.TransportNode - -interface PowerPathfindingNode { - /** - * For use in pathfinding. When entering from previous node, get the list of available next nodes. Mostly used by the flood fill. - **/ - fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt deleted file mode 100644 index 95f6785ee1..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SolarPanelNode.kt +++ /dev/null @@ -1,273 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.transport.node.type.general.UnTransferableNode -import net.horizonsend.ion.server.features.transport.node.util.separateNode -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_COVERED_POSITIONS -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_DETECTORS -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SOLAR_CELL_EXTRACTORS -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded -import org.bukkit.GameRule -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace.DOWN -import org.bukkit.block.BlockFace.UP -import org.bukkit.block.data.AnaloguePowerable -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType.LONG_ARRAY -import java.util.concurrent.ConcurrentHashMap -import java.util.function.Consumer - -/** - * Represents a solar panel, or multiple - **/ -class SolarPanelNode(override val manager: PowerNodeManager) : MultiNode(), PowerPathfindingNode { - override val type: NodeType = NodeType.SOLAR_PANEL_NODE - /** The positions of extractors in this solar panel */ - private val extractorPositions = ConcurrentHashMap.newKeySet() - - /** The positions of daylight detectors in this solar panel */ - private val detectorPositions = ConcurrentHashMap.newKeySet() - - /** The number of solar cells contained in this node */ - private val cellNumber: Int get() = extractorPositions.size - - override fun isTransferableTo(node: TransportNode): Boolean { - if (node is SolarPanelNode && node.exitDistance > this.exitDistance) return false - - // Solar panels should be able to transfer through extractors and other solar panels - return node !is UnTransferableNode - } - - /** - * The distance this solar node is from the nearest exit of the solar field - * This value will be -1 if there are no exits present - **/ - private var exitDistance: Int = 0 - - /** - * Calculate the distance to an exit of a solar field - * This method is run upon neighbor unloads - **/ - private fun calculateExitDistance() { - val neighbors = cachedTransferable - - // Transferable node provides an exit - if (neighbors.any { it !is SolarPanelNode }) { - exitDistance = 0 - return - } - - val solars = neighbors.filterIsInstance() - if (solars.isEmpty()) { - exitDistance = -1 - return - } - - exitDistance = solars.minOf { it.exitDistance } + 1 - } - - /** - * Store the last time this node successfully transferred power, so that a difference can be gained. - * - * This will be used to calculate the amount of power generated, so it remains consistent, even in laggy conditions. - **/ - private var lastTicked: Long = System.currentTimeMillis() - - /** - * Get the power and reset the last ticked time - **/ - fun tickAndGetPower(): Int { - val power = getPower() - - lastTicked = System.currentTimeMillis() - - return power - } - - /** - * Returns the amount of power between ticks - **/ - fun getPower(): Int { - val daylightMultiplier: Double = if ( - manager.world.environment == World.Environment.NORMAL && - manager.world.getGameRuleValue(GameRule.DO_DAYLIGHT_CYCLE) == true - ) { - getPowerRatio() - } else 0.5 - - val time = System.currentTimeMillis() - val diff = time - this.lastTicked - - return ((diff / 1000.0) * POWER_PER_SECOND * cellNumber * daylightMultiplier).toInt() - } - - /** - * Calculates the light level at the detectors - **/ - private fun getPowerRatio(): Double { - val total = detectorPositions.size * 15 - val sum = detectorPositions.sumOf { - val data = getBlockDataSafe(manager.world, getX(it), getY(it), getZ(it)) ?: return@sumOf 0 - if (data !is AnaloguePowerable) return@sumOf 0 - - data.power - } - - return sum.toDouble() / total.toDouble() - } - - /** - * Execute the provided consumer across every interconnected solar node - * - * WARNING: use this carefully - **/ - private fun traverseField(visited: MutableList = mutableListOf(), consumer: Consumer) { - if (visited.contains(this)) return - - consumer.accept(this) - - visited.add(this) - - getTransferableNodes().filterIsInstance().filterNot { visited.contains(it) }.forEach(consumer) - } - - /** - * Returns whether the individual solar panel from the extractor location is intact - **/ - fun isIntact(world: World, extractorKey: BlockKey): Boolean { - return matchesSolarPanelStructure(world, extractorKey) - } - - // If relations have changed, update the exit distances of the whole field - override fun buildRelations(position: BlockKey) { - super.buildRelations(position) - - // Calculate exit distance after relations have been built - traverseField { it.calculateExitDistance() } - } - - /* - * When the neighbor changes, re-calculate the exit distances - */ - override fun neighborChanged(neighbor: TransportNode) { - traverseField { it.calculateExitDistance() } - } - - override fun handlePositionRemoval(position: BlockKey) { - isDead = true - - removePosition(position) - - if (separateNode(this)) { - positions.clear() - clearRelations() - } - } - - fun addPosition(extractorKey: BlockKey, diamondKey: BlockKey, detectorKey: BlockKey): SolarPanelNode { - extractorPositions += extractorKey - - // Make sure there isn't still an extractor - manager.extractors.remove(extractorKey) - addPosition(extractorKey) - buildRelations(extractorKey) - - positions += diamondKey - positions += detectorKey - - detectorPositions += detectorKey - - for (position: BlockKey in positions) { - manager.nodes[position] = this - buildRelations(position) - } - - storedCenter = calculateCenter() - - return this - } - - private fun removePosition(axisPosition: BlockKey) { - val extractorPos = if (extractorPositions.contains(axisPosition)) axisPosition else (1..2).firstNotNullOf { offset -> - getRelative(axisPosition, DOWN, offset).takeIf { extractorPositions.contains(it) } - } - - val otherPositions = (1..2).map { getRelative(extractorPos, UP, it) } - - positions.remove(extractorPos) - extractorPositions.remove(extractorPos) - manager.nodes.remove(extractorPos) - - for (otherPos: BlockKey in otherPositions) { - positions.remove(otherPos) - manager.nodes.remove(otherPos) - } - - storedCenter = calculateCenter() - } - - override fun addBack(position: BlockKey) { - manager.nodeFactory.addSolarPanel(position, handleRelationships = false) - } - - override fun loadIntoNetwork() { - super.loadIntoNetwork() - manager.solarPanels += this - } - - override fun storeData(persistentDataContainer: PersistentDataContainer) { - persistentDataContainer.set(NODE_COVERED_POSITIONS, LONG_ARRAY, positions.toLongArray()) - persistentDataContainer.set(SOLAR_CELL_EXTRACTORS, LONG_ARRAY, extractorPositions.toLongArray()) - persistentDataContainer.set(SOLAR_CELL_DETECTORS, LONG_ARRAY, detectorPositions.toLongArray()) - } - - override fun loadData(persistentDataContainer: PersistentDataContainer) { - val coveredPositions = persistentDataContainer.get(NODE_COVERED_POSITIONS, LONG_ARRAY) - coveredPositions?.let { positions.addAll(it.asIterable()) } - - val extractors = persistentDataContainer.get(SOLAR_CELL_EXTRACTORS, LONG_ARRAY) - extractors?.let { extractorPositions.addAll(it.asIterable()) } - - val detectors = persistentDataContainer.get(SOLAR_CELL_DETECTORS, LONG_ARRAY) - detectors?.let { detectorPositions.addAll(it.asIterable()) } - } - - override fun getPathfindingResistance(previousNode: TransportNode?, nextNode: TransportNode?): Int { - // Further encourage the way out - return 1000 - exitDistance - } - - companion object { - const val POWER_PER_SECOND = 5 - - fun matchesSolarPanelStructure(world: World, extractorPosition: BlockKey): Boolean { - val extractorBlock = getBlockIfLoaded(world, getX(extractorPosition), getY(extractorPosition), getZ(extractorPosition)) - if (extractorBlock?.type != Material.CRAFTING_TABLE) return false - - val diamond = extractorBlock.getRelativeIfLoaded(UP) - if (diamond?.type != Material.DIAMOND_BLOCK) return false - - val cell = diamond.getRelativeIfLoaded(UP) - return cell?.type == Material.DAYLIGHT_DETECTOR - } - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable - - override fun toString(): String = "(SOLAR PANEL NODE:" + - " Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes, " + - "distance = $exitDistance," + - " powerRatio = ${getPowerRatio()}, " + - "location = ${getCenter()}" -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt deleted file mode 100644 index dd19c44842..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/type/power/SpongeNode.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.type.power - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.NodeType.SPONGE_NODE -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i - -/** - * Represents a sponge [omnidirectional pipe] - * - * Since there is no use in keeping the individual steps, all touching sponges are consolidated into a single node with multiple inputs / outputs, weighted evenly - **/ -class SpongeNode(network: PowerNodeManager) : JunctionNode(network), PowerPathfindingNode { - override val type: NodeType = SPONGE_NODE - - override fun addBack(position: BlockKey) { - manager.nodeFactory.addJunctionNode(position, type, handleRelationships = false) - } - - override fun getNextNodes(previous: TransportNode, destination: TransportNode?): ArrayDeque = cachedTransferable - - override fun toString(): String = "(SPONGE NODE: ${positions.size} positions, Transferable to: ${getTransferableNodes().joinToString { it.javaClass.simpleName }} nodes) location = ${toVec3i(positions.random())}" -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt deleted file mode 100644 index 2b6b570409..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeFactory.kt +++ /dev/null @@ -1,73 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.util - -import net.horizonsend.ion.server.features.transport.node.NodeType -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.type.SingleNode -import net.horizonsend.ion.server.features.transport.node.type.general.DirectionalNode -import net.horizonsend.ion.server.features.transport.node.type.general.JunctionNode -import net.horizonsend.ion.server.features.transport.node.type.general.LinearNode -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.faces -import org.bukkit.Axis -import org.bukkit.block.BlockFace -import org.bukkit.block.data.BlockData - -abstract class NodeFactory>(val network: T) { - /** - * Create and handle placement of a node at the position, if one should be created - **/ - abstract fun create(key: BlockKey, data: BlockData): Boolean - - inline fun > addJunctionNode(position: BlockKey, type: NodeType, handleRelationships: Boolean = true) { - val neighbors = getNeighborNodes(position, network.nodes).values.filterIsInstanceTo>(mutableListOf()) - - val finalNode = when (neighbors.size) { - 0 -> newNode(type).addPosition(position) // New sponge node - 1 -> neighbors.firstOrNull()?.addPosition(position) ?: newNode(type).addPosition(position) // Consolidate into neighbor - in 2..6 -> handleMerges(neighbors).addPosition(position) // Join multiple neighbors together - - else -> throw NotImplementedError() - } - if (handleRelationships) finalNode.rebuildRelations() - } - - inline fun > addLinearNode(position: BlockKey, axis: Axis, type: NodeType, handleRelationships: Boolean = true) { - // The neighbors in the direction of the wire's facing, that are also facing that direction - val neighbors = getNeighborNodes(position, network.nodes, axis.faces.toList()) - .values - .filterIsInstance() - .filterTo(mutableListOf()) { it.axis == axis && it.type == type } - - val finalNode = when (neighbors.size) { - 0 -> newNode(type).addPosition(position).setAxis(axis) - 1 -> neighbors.firstOrNull()?.addPosition(position) ?: newNode(type).addPosition(position).setAxis(axis) - 2 -> handleMerges(neighbors).addPosition(position) - - else -> throw IllegalArgumentException("Linear node had more than 2 neighbors") - } - - if (handleRelationships) finalNode.rebuildRelations() - } - - fun addSimpleSingleNode(position: BlockKey, type: NodeType) { - val new = type.newInstance(network) as SingleNode - - new.position = position - new.onPlace(position) - - network.nodes[position] = new - } - - fun addDirectionalNode(position: BlockKey, direction: BlockFace, type: NodeType) { - val new = type.newInstance(network) as DirectionalNode - - new.position = position - new.direction = direction - new.onPlace(position) - - network.nodes[position] = new - } - - inline fun newNode(type: NodeType): T = type.newInstance(network) as T -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt deleted file mode 100644 index 968ce3eb38..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodeUtils.kt +++ /dev/null @@ -1,147 +0,0 @@ -package net.horizonsend.ion.server.features.transport.node.util - -import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.cache.TransportCache -import net.horizonsend.ion.server.features.transport.node.TransportNode -import net.horizonsend.ion.server.features.transport.node.manager.FluidNodeManager -import net.horizonsend.ion.server.features.transport.node.manager.NodeManager -import net.horizonsend.ion.server.features.transport.node.manager.PowerNodeManager -import net.horizonsend.ion.server.features.transport.node.type.MultiNode -import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.popMaxByOrNull -import org.bukkit.NamespacedKey -import org.bukkit.block.BlockFace -import java.util.LinkedList - -fun getNeighborNodes(position: BlockKey, nodes: Map, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.associateWithNotNull { - val x = getX(position) - val y = getY(position) - val z = getZ(position) - - nodes[toBlockKey(x + it.modX, y + it.modY, z + it.modZ)] -} - -fun getNeighborNodes(position: BlockKey, nodes: Collection, checkFaces: Collection = ADJACENT_BLOCK_FACES) = checkFaces.mapNotNull { - val x = getX(position) - val y = getY(position) - val z = getZ(position) - - toBlockKey(x + it.modX, y + it.modY, z + it.modZ).takeIf { key -> nodes.contains(key) } -} - -/** - * Merge the provided nodes into the largest node [by position] in the collection - * - * @return the node that the provided were merged into - **/ -fun > handleMerges(neighbors: MutableCollection): Self { - // Get the largest neighbor - val largestNeighbor = neighbors.popMaxByOrNull { - it.positions.size - } ?: throw ConcurrentModificationException("Node removed during processing") - - // Merge all other connected nodes into the largest - neighbors.forEach { - it.drainTo(largestNeighbor) - } - - return largestNeighbor -} - -fun > separateNode(node: G): Boolean { - // Generate the grid nodes isolated from each other. - val splitGraphs: List> = separateNodePositions(node) - - if (splitGraphs.size <= 1) return false - - // Create new nodes - splitGraphs.forEach { node.ofPositions(it) } - - return true -} - -/** - * Splits a multi node's positions into multiple nodes - * https://github.com/CoFH/ThermalDynamics/blob/1.20.x/src/main/java/cofh/thermal/dynamics/common/grid/GridContainer.java#L394 - **/ -fun > separateNodePositions(node: T): List> { - val seen: MutableSet = HashSet() - val stack = LinkedList() - val separated: MutableList> = LinkedList() - - while (true) { - var first: BlockKey? = null - - // Find next node in graph we haven't seen. - for (position in node.positions) { - if (!seen.contains(position)) { - first = position - break - } - } - - // We have discovered all nodes, exit. - if (first == null) break - - // Start recursively building out all nodes in this sub-graph - val subGraph: MutableSet = HashSet() - - stack.push(first) - - while (!stack.isEmpty()) { - val entry = stack.pop() - - if (seen.contains(entry)) continue - - stack.addAll(node.adjacentPositions(entry)) - seen.add(entry) - subGraph.add(entry) - } - - separated.add(subGraph) - } - - return separated -} - -enum class NetworkType(val namespacedKey: NamespacedKey) { - POWER(NamespacedKeys.POWER_TRANSPORT) { - override fun get(chunk: IonChunk): PowerTransportCache { - return chunk.transportNetwork.powerNodeManager.network - } - - override fun get(ship: ActiveStarship): PowerTransportCache { - return ship.transportManager.powerNodeManager.network - } - }, - FLUID(NamespacedKeys.FLUID_TRANSPORT) { - override fun get(chunk: IonChunk): FluidTransportCache { - return chunk.transportNetwork.fluidNodeManager.network - } - - override fun get(ship: ActiveStarship): FluidTransportCache { - return ship.transportManager.fluidNodeManager.network - } - }, - - - ; - - abstract fun get(chunk: IonChunk): TransportCache - abstract fun get(ship: ActiveStarship): TransportCache - - companion object { - private val byKey = entries.associateBy { it.namespacedKey } - operator fun get(key: NamespacedKey): NetworkType = byKey[key]!! - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt new file mode 100644 index 0000000000..9e1d3f37de --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt @@ -0,0 +1,41 @@ +package net.horizonsend.ion.server.features.transport.util + +import net.horizonsend.ion.server.features.starship.active.ActiveStarship +import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.NamespacedKey + +enum class NetworkType(val namespacedKey: NamespacedKey) { + POWER(NamespacedKeys.POWER_TRANSPORT) { + override fun get(chunk: IonChunk): PowerTransportCache { + return chunk.transportNetwork.powerNodeManager.network + } + + override fun get(ship: ActiveStarship): PowerTransportCache { + return ship.transportManager.powerNodeManager.network + } + }, + FLUID(NamespacedKeys.FLUID_TRANSPORT) { + override fun get(chunk: IonChunk): FluidTransportCache { + return chunk.transportNetwork.fluidNodeManager.network + } + + override fun get(ship: ActiveStarship): FluidTransportCache { + return ship.transportManager.fluidNodeManager.network + } + }, + + + ; + + abstract fun get(chunk: IonChunk): TransportCache + abstract fun get(ship: ActiveStarship): TransportCache + + companion object { + private val byKey = entries.associateBy { it.namespacedKey } + operator fun get(key: NamespacedKey): NetworkType = byKey[key]!! + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index ed10fadcb2..ffc0ef574d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/node/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.node.util +package net.horizonsend.ion.server.features.transport.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.LongOpenHashSet @@ -97,7 +97,8 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: queueSet.remove(wrapper.pos) } - queueAdd(PathfindingNodeWrapper( + queueAdd( + PathfindingNodeWrapper( world = world, pos = fromPos, node = fromType, @@ -106,7 +107,8 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: type = type, g = 0, f = 0 - )) + ) + ) val visited = IntOpenHashSet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index e3d1e976ac..9e912310e6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.world.chunk import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.manager.ChunkMultiblockManager -import net.horizonsend.ion.server.features.transport.node.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.data.DataFixers import net.horizonsend.ion.server.listener.SLEventListener From eb61363433b2317ec0165724fdcef8f9a80d1a43 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 10 Nov 2024 23:02:19 -0600 Subject: [PATCH 268/500] move files around --- .../main/kotlin/net/horizonsend/ion/server/IonServer.kt | 1 + .../ion/server/command/admin/IonChunkCommand.kt | 2 +- .../client/display/modular/display/FlowMeterDisplay.kt | 2 +- .../server/features/custom/items/misc/MultimeterItem.kt | 2 +- .../features/multiblock/manager/ChunkMultiblockManager.kt | 2 +- .../features/multiblock/manager/MultiblockManager.kt | 2 +- .../features/multiblock/manager/ShipMultiblockManager.kt | 2 +- .../{configuration => }/TransportConfiguration.kt | 2 +- .../server/features/transport/cache/state/CacheState.kt | 8 -------- .../features/transport/manager/ChunkTransportManager.kt | 4 ++-- .../features/transport/manager/ShipTransportManager.kt | 4 ++-- .../server/features/transport/manager/TransportManager.kt | 4 ++-- .../transport/manager/holders/ChunkNetworkHolder.kt | 4 ++-- .../features/transport/manager/holders/NetworkHolder.kt | 4 ++-- .../transport/manager/holders/ShipNetworkHolder.kt | 4 ++-- .../server/features/transport/nodes/cache/CacheState.kt | 6 ++++++ .../features/transport/{ => nodes}/cache/CachedNode.kt | 2 +- .../transport/{ => nodes}/cache/FluidTransportCache.kt | 2 +- .../transport/{ => nodes}/cache/NodeCacheFactory.kt | 2 +- .../transport/{ => nodes}/cache/PowerTransportCache.kt | 6 +++--- .../transport/{ => nodes}/cache/TransportCache.kt | 3 +-- .../server/features/transport/{ => util}/IonChangeSet.kt | 3 ++- .../ion/server/features/transport/util/NetworkType.kt | 6 +++--- .../ion/server/features/transport/util/NodePathfinding.kt | 2 +- .../ion/server/listener/misc/WorldEditListener.kt | 2 +- 25 files changed, 40 insertions(+), 41 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{configuration => }/TransportConfiguration.kt (73%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => nodes}/cache/CachedNode.kt (90%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => nodes}/cache/FluidTransportCache.kt (85%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => nodes}/cache/NodeCacheFactory.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => nodes}/cache/PowerTransportCache.kt (97%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => nodes}/cache/TransportCache.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{ => util}/IonChangeSet.kt (94%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt index 7ac5061840..e3a2e849a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/IonServer.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.ConfigurationFiles.configurationFolder import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.client.networking.packets.ShipData +import net.horizonsend.ion.server.features.transport.TransportConfiguration import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.features.world.generation.generators.bukkit.EmptyChunkGenerator import net.horizonsend.ion.server.features.world.generation.generators.bukkit.SpaceBiomeProvider diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 816eb65fb5..ba2bce2242 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index 5c10b72ffc..d5f45e3a60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.client.display.modular.display -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.kyori.adventure.text.Component class FlowMeterDisplay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index e89dccdd7e..5261a606b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.transport.cache.CachedNode +import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.transport.util.PathfindingNodeWrapper import net.horizonsend.ion.server.features.transport.util.calculatePathResistance diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index e4a6ba916a..42ee4f3be3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index e9d9ebbad7..b5a9bbabff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultibl import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index f298300d69..8972f30197 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt similarity index 73% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt index 76745d4a74..ea05574b30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/configuration/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.configuration +package net.horizonsend.ion.server.features.transport import kotlinx.serialization.Serializable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt deleted file mode 100644 index 59dfc04014..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/state/CacheState.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.horizonsend.ion.server.features.transport.cache.state - -import net.horizonsend.ion.server.features.transport.cache.CachedNode - -sealed interface CacheState { - data object Empty: CacheState - data class Present(val node: CachedNode): CacheState -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index c7db98b038..958c666c0e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ChunkNetworkHolder diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 0f1727d864..1bfd128ed0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ShipNetworkHolder diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index d7af7d24ae..860ae758c1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.manager -import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt index 227d6c4eaf..f0184fc749 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.cache.CachedNode -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.world.chunk.IonChunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt index 1782ad7d57..7f77e51e2c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.cache.CachedNode -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt index ac5126c4d3..5893f762cf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.cache.CachedNode -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.world.chunk.IonChunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt new file mode 100644 index 0000000000..41735351aa --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.nodes.cache + +sealed interface CacheState { + data object Empty: CacheState + data class Present(val node: CachedNode): CacheState +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt similarity index 90% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt index cb34c003b4..e57ebf154b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/CachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.cache +package net.horizonsend.ion.server.features.transport.nodes.cache import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt similarity index 85% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 9eb525d10e..ad835f9a95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.cache +package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.util.NetworkType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index d0e5b3dfa6..0874c3db01 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.cache +package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt similarity index 97% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 8cfb7ee6ce..34e816afe5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.transport.cache +package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache.PowerNode.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache.PowerNode.PowerInputNode +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.transport.util.calculatePathResistance diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 8b11ae4362..a0e045712c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,7 +1,6 @@ -package net.horizonsend.ion.server.features.transport.cache +package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap -import net.horizonsend.ion.server.features.transport.cache.state.CacheState import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt index ff682b292c..5d1d4b8791 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport +package net.horizonsend.ion.server.features.transport.util import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet import com.sk89q.jnbt.CompoundTag @@ -8,6 +8,7 @@ import com.sk89q.worldedit.world.World import com.sk89q.worldedit.world.biome.BiomeType import com.sk89q.worldedit.world.block.BlockTypesCache import net.horizonsend.ion.server.features.multiblock.MultiblockEntities +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt index 9e1d3f37de..f8a8f8da80 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt @@ -1,9 +1,9 @@ package net.horizonsend.ion.server.features.transport.util import net.horizonsend.ion.server.features.starship.active.ActiveStarship -import net.horizonsend.ion.server.features.transport.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.NamespacedKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index ffc0ef574d..cadb7bc975 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.server.features.transport.cache.CachedNode +import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt index 96747ec893..fd9669c395 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/WorldEditListener.kt @@ -6,7 +6,7 @@ import com.sk89q.worldedit.event.Event import com.sk89q.worldedit.event.extent.EditSessionEvent import com.sk89q.worldedit.util.eventbus.Subscribe import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.transport.IonChangeSet +import net.horizonsend.ion.server.features.transport.util.IonChangeSet import org.bukkit.Bukkit object WorldEditListener : IonServerComponent(true) { From bffaf4c04f0fd1e928092feb7e29fd394f275408 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 10 Nov 2024 23:51:12 -0600 Subject: [PATCH 269/500] Register extractors in the new system --- .../server/command/admin/IonChunkCommand.kt | 13 +++ .../command/qol/FixExtractorsCommand.kt | 12 ++- .../multiblock/shape/MultiblockShape.kt | 4 +- .../factory/StarshipFactoryPrinter.kt | 6 +- .../server/features/transport/NewTransport.kt | 90 ++++++++++++++++++- .../extractors/ChunkExtractorManager.kt | 18 +++- .../manager/extractors/ExtractorManager.kt | 7 ++ .../extractors/ShipExtractorManager.kt | 8 ++ .../features/transport/old/Extractors.kt | 27 +----- 9 files changed, 141 insertions(+), 44 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index ba2bce2242..c6cb08e7f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -75,6 +75,19 @@ object IonChunkCommand : SLCommand() { } } + @Subcommand("dump extractors") + @CommandCompletion("power") /* |item|gas") */ + fun dumpExtractors(sender: Player, network: NetworkType) { + val ionChunk = sender.chunk.ion() + val extractors = network.get(ionChunk).holder.getExtractorManager() + + sender.information("${extractors.getExtractors().size} covered position(s).") + + extractors.getExtractors().forEach { pos -> + sender.highlightBlock(toVec3i(pos), 50L) + } + } + @Subcommand("dump") @CommandCompletion("power") fun dumpNetwork(sender: Player, network: NetworkType) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt index a22d77f6ae..92921e48da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt @@ -6,8 +6,8 @@ import co.aikar.commands.annotation.Default import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand -import net.horizonsend.ion.server.features.transport.old.Extractors -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player @@ -35,14 +35,12 @@ object FixExtractorsCommand : SLCommand() { val block = sender.world.getBlockAt(x, y, z) - if (block.type != Extractors.EXTRACTOR_BLOCK) continue + if (block.type != EXTRACTOR_TYPE) continue - val vec3i = Vec3i(x, y, z) - - if (Extractors.contains(sender.world, vec3i)) continue + if (NewTransport.isExtractor(sender.world, x, y, z)) continue count++ - Extractors.add(sender.world, vec3i) + NewTransport.addExtractor(sender.world, x, y, z) } sender.success("Registered $count new extractors") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index ff6bee07b9..c144503886 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUI import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING -import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES @@ -415,7 +415,7 @@ class MultiblockShape { fun daylightSensor() = filteredTypes("daylight sensor") { it.isDaylightSensor } fun craftingTable() = type(Material.CRAFTING_TABLE) - fun extractor() = type(Extractors.EXTRACTOR_BLOCK) + fun extractor() = type(EXTRACTOR_TYPE) fun glowstone() = type(Material.GLOWSTONE) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt index ae1bddf3b1..9eb24475bc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt @@ -2,9 +2,9 @@ package net.horizonsend.ion.server.features.starship.factory import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.configuration.ConfigurationFiles -import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ @@ -183,7 +183,7 @@ class StarshipFactoryPrinter( val blockZ = blockKeyZ(key) world.setNMSBlockData(blockX, blockY, blockZ, data) - if (data.bukkitMaterial == Extractors.EXTRACTOR_BLOCK) Extractors.add(world, Vec3i(blockX, blockY, blockZ)) + if (data.bukkitMaterial == EXTRACTOR_TYPE) NewTransport.addExtractor(world, blockX, blockY, blockZ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index d4c2f523a1..d103c5a06e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -1,11 +1,22 @@ package net.horizonsend.ion.server.features.transport +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.starship.event.build.StarshipBreakBlockEvent +import net.horizonsend.ion.server.features.starship.event.build.StarshipPlaceBlockEvent import net.horizonsend.ion.server.features.transport.manager.TransportManager -import net.horizonsend.ion.server.features.transport.old.Extractors +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import org.bukkit.Material import org.bukkit.World +import org.bukkit.event.EventHandler +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockPistonExtendEvent +import org.bukkit.event.block.BlockPistonRetractEvent +import org.bukkit.event.block.BlockPlaceEvent import java.util.Timer import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ExecutorService @@ -21,7 +32,8 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t override fun onEnable() { executor = Executors.newFixedThreadPool(64, Tasks.namedThreadFactory("wire-transport")) - val interval: Long = (1000 / Extractors.extractorTicksPerSecond).toLong() + val interval: Long = IonServer.transportSettings.extractorTickIntervalMS + monitorThread = fixedRateTimer(name = "Extractor Tick", daemon = true, initialDelay = interval, period = interval) { transportManagers.forEach { try { @@ -47,7 +59,79 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } fun invalidateCache(world: World, x: Int, y: Int, z: Int) { - val chunk = IonChunk[world, x.shr(4), z.shr(4)] ?: return + val chunk = IonChunk.getFromWorldCoordinates(world, x, z) ?: return chunk.transportNetwork.invalidateCache(x, y, z) } + + private fun getExtractorManager(world: World, x: Int, z: Int): ExtractorManager? { + return IonChunk.getFromWorldCoordinates(world, x, z)?.transportNetwork?.extractorManager + } + + fun addExtractor(world: World, x: Int, y: Int, z: Int, ensureExtractor: Boolean = false) { + getExtractorManager(world, x, z)?.registerExtractor(x, y, z, ensureExtractor) + } + + fun removeExtractor(world: World, x: Int, y: Int, z: Int) { + getExtractorManager(world, x, z)?.removeExtractor(x, y, z) + } + + fun isExtractor(world: World, x: Int, y: Int, z: Int): Boolean { + return getExtractorManager(world, x, z)?.isExtractor(x, y, z) ?: false + } + + fun ensureExtractor(world: World, x: Int, y: Int, z: Int) { + val type = getBlockTypeSafe(world, x, y, z) ?: return + val isExtractor = isExtractor(world, x, y, z) + if (type == EXTRACTOR_TYPE && !isExtractor) addExtractor(world, x, y, z) + if (type != EXTRACTOR_TYPE && isExtractor) removeExtractor(world, x, y, z) + } + + fun handleBlockEvent(world: World, x: Int, y: Int, z: Int, previousType: Material?, newType: Material) = Tasks.async { + if (previousType == EXTRACTOR_TYPE && newType != EXTRACTOR_TYPE) return@async removeExtractor(world, x, y, z) + if (newType == EXTRACTOR_TYPE) return@async addExtractor(world, x, y, z) + } + + @EventHandler + fun onPlayerBlockPlace(event: BlockPlaceEvent) { + val block = event.block + handleBlockEvent(block.world, block.x, block.y, block.z, event.blockReplacedState.type, block.type) + } + + @EventHandler + fun onPlayerBlockBreak(event: BlockBreakEvent) { + val block = event.block + handleBlockEvent(block.world, block.x, block.y, block.z, block.type, Material.AIR) + } + + @EventHandler + fun onShipBlockPlace(event: StarshipPlaceBlockEvent) { + val block = event.block + handleBlockEvent(block.world, block.x, block.y, block.z, Material.AIR, block.type) + } + + @EventHandler + fun onShipBlockBreak(event: StarshipBreakBlockEvent) { + val block = event.block + handleBlockEvent(block.world, block.x, block.y, block.z, event.block.type, Material.AIR) + } + + @EventHandler + fun handlePistonExtend(event: BlockPistonExtendEvent) { + val piston = event.block + Tasks.sync { + for (block in event.blocks) { + ensureExtractor(piston.world, piston.x, piston.y, piston.z) + } + } + } + + @EventHandler + fun handlePistonRetract(event: BlockPistonRetractEvent) { + val piston = event.block + Tasks.sync { + for (block in event.blocks) { + ensureExtractor(piston.world, piston.x, piston.y, piston.z) + } + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 96ecb8d32b..a478c8d79d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -11,24 +11,34 @@ import org.bukkit.persistence.PersistentDataType class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManager() { var extractors = LongOpenHashSet() - override fun getExtractors(): List { + private val mutex = Any() + + override fun getExtractors(): List = synchronized(mutex) { return extractors.toList() } - override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { + override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean = synchronized(mutex) { if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != EXTRACTOR_TYPE) return false if (!manager.chunk.isInBounds(x, y, z)) return false extractors.add(toBlockKey(x, y, z)) return true } - override fun isExtractor(key: BlockKey): Boolean { + override fun removeExtractor(x: Int, y: Int, z: Int): Boolean = synchronized(mutex) { + return extractors.remove(toBlockKey(x, y, z)) + } + + override fun removeExtractor(key: BlockKey): Boolean = synchronized(mutex) { + return extractors.remove(key) + } + + override fun isExtractor(key: BlockKey): Boolean = synchronized(mutex) { return extractors.contains(key) } private val pdc get() = manager.chunk.inner.persistentDataContainer - override fun onLoad() { + override fun onLoad() = synchronized(mutex) { val existing = pdc.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) ?: return extractors = LongOpenHashSet(existing) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index 93559e1ed3..60ba9eec18 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -4,12 +4,19 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Material abstract class ExtractorManager { abstract fun getExtractors(): List + fun registerExtractor(key: BlockKey, ensureExtractor: Boolean): Boolean = registerExtractor(getX(key), getY(key), getZ(key), ensureExtractor) abstract fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean + + abstract fun removeExtractor(key: BlockKey): Boolean + abstract fun removeExtractor(x: Int, y: Int, z: Int): Boolean + + fun isExtractor(x: Int, y: Int, z: Int): Boolean = isExtractor(toBlockKey(x, y, z)) abstract fun isExtractor(key: BlockKey): Boolean companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index 4b4457d55d..ac9ec49b35 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -23,6 +23,14 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { return true } + override fun removeExtractor(x: Int, y: Int, z: Int): Boolean { + return extractors.remove(toBlockKey(x, y, z)) + } + + override fun removeExtractor(key: BlockKey): Boolean { + return extractors.remove(key) + } + fun loadExtractors() { starship.iterateBlocks { x, y, z -> registerExtractor(x, y, z, true) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt index b3daf62383..89f74b67ea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.old import com.google.gson.Gson import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters @@ -28,17 +29,10 @@ import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.inventory.InventoryHolder import java.io.File import java.nio.file.Files -import java.util.Timer import java.util.concurrent.ConcurrentHashMap import kotlin.collections.set -import kotlin.concurrent.fixedRateTimer object Extractors : IonServerComponent() { - const val extractorTicksPerSecond = 1.0 - - val EXTRACTOR_BLOCK = Material.CRAFTING_TABLE - - private lateinit var timer: Timer private val worldDataMap = ConcurrentHashMap>() @@ -47,29 +41,12 @@ object Extractors : IonServerComponent() { override fun onEnable() { return IonServer.server.worlds.forEach(Extractors::loadExtractors) - - Tasks.asyncRepeat(20 * 2, 20 * 2) { - worldDataMap.keys.forEach { saveExtractors(it) } - } - listen { event -> loadExtractors(event.world) } - listen { event -> unloadExtractors(event.world) } - - val interval: Long = (1000 / extractorTicksPerSecond).toLong() - - timer = fixedRateTimer(name = "Extractor Tick", daemon = true, initialDelay = interval, period = interval) { - try { - worldDataMap.keys.forEach(Extractors::tickExtractors) - } catch (exception: Exception) { - exception.printStackTrace() - } - } } override fun onDisable() { IonServer.server.worlds.forEach(Extractors::unloadExtractors) - timer.cancel() } //region Loading and saving @@ -143,7 +120,7 @@ object Extractors : IonServerComponent() { // this also ensures the chunk is loaded val extractorMaterial: Material? = getBlockTypeSafe(world, x, y, z) - if (extractorMaterial != EXTRACTOR_BLOCK) { + if (extractorMaterial != ExtractorManager.EXTRACTOR_TYPE) { continue } From 51d16e37f92139299a82a11bf17c255d90d28c43 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 11 Nov 2024 12:46:54 -0600 Subject: [PATCH 270/500] Add input manager --- .../manager/ChunkMultiblockManager.kt | 2 + .../multiblock/manager/MultiblockManager.kt | 3 + .../manager/ShipMultiblockManager.kt | 5 + .../manager/ChunkTransportManager.kt | 9 +- .../transport/manager/ShipTransportManager.kt | 11 +- .../transport/manager/TransportManager.kt | 7 +- .../transport/nodes/inputs/InputManager.kt | 104 ++++++++++++++++++ .../nodes/inputs/ShipInputManager.kt | 5 + .../nodes/inputs/WorldInputManager.kt | 5 + .../transport/nodes/inputs/WorldInputs.kt | 5 + .../ion/server/features/world/IonWorld.kt | 6 +- 11 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/ShipInputManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputs.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 42ee4f3be3..87f9dd89ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES @@ -18,6 +19,7 @@ import org.slf4j.Logger class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManager(log) { override val world: World = chunk.world + override fun getInputManager(): InputManager = chunk.region.world.inputManager /** * Logic upon the chunk being saved diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index b5a9bbabff..73a7e68e65 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -28,6 +29,8 @@ abstract class MultiblockManager(val log: Logger) { abstract val world: World + abstract fun getInputManager(): InputManager + abstract fun save() abstract fun markChanged() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 8972f30197..a0bfedf317 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -36,6 +37,10 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override val world get() = starship.world + override fun getInputManager(): InputManager { + return starship.transportManager.getInputProvider() + } + override fun save() {} override fun getSignUnsavedTime(): Long = 0 override fun markChanged() {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 958c666c0e..86e3a290fb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -1,11 +1,12 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -18,6 +19,10 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { override val fluidNodeManager = ChunkNetworkHolder(this) { FluidTransportCache(it) } // val pipeGrid = PowerNodeManager(this) // TODO + override fun getInputProvider(): InputManager { + return chunk.region.world.inputManager + } + fun setup() { powerNodeManager.handleLoad() fluidNodeManager.handleLoad() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 1bfd128ed0..6327aae0c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -3,13 +3,16 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ShipNetworkHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager +import net.horizonsend.ion.server.features.transport.nodes.inputs.ShipInputManager class ShipTransportManager(val starship: Starship) : TransportManager() { override val extractorManager: ShipExtractorManager = ShipExtractorManager(starship) + private val inputManager = ShipInputManager(this) override val powerNodeManager = ShipNetworkHolder(this) { PowerTransportCache(it) } override val fluidNodeManager = ShipNetworkHolder(this) { FluidTransportCache(it) } @@ -31,4 +34,8 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { fun displace(movement: StarshipMovement) { } + + override fun getInputProvider(): InputManager { + return inputManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 860ae758c1..65a56f1497 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -1,15 +1,18 @@ package net.horizonsend.ion.server.features.transport.manager -import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager abstract class TransportManager { abstract val extractorManager: ExtractorManager abstract val powerNodeManager: NetworkHolder abstract val fluidNodeManager: NetworkHolder + abstract fun getInputProvider(): InputManager + fun tick() { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt new file mode 100644 index 0000000000..dcb458df31 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt @@ -0,0 +1,104 @@ +package net.horizonsend.ion.server.features.transport.nodes.inputs + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import java.util.concurrent.ConcurrentHashMap + +abstract class InputManager { + private val typeManagers = ConcurrentHashMap() + + private fun getTypeManager(type: NetworkType): TypeManager { + return typeManagers.getOrPut(type) { TypeManager(this, type) } + } + + fun registerInput(type: NetworkType, location: BlockKey, holder: MultiblockEntity) { + getTypeManager(type).add(location, holder) + } + + fun deRegisterInput(type: NetworkType, location: BlockKey, holder: MultiblockEntity) { + getTypeManager(type).remove(location, holder) + } + + fun getHolders(type: NetworkType, location: BlockKey): Set { + return getTypeManager(type).getAllHolders(location) + } + + class TypeManager(val manager: InputManager, val type: NetworkType) { + private val inputLocations = Long2ObjectOpenHashMap() + + fun getAll() = inputLocations.clone() + + fun add(location: BlockKey, holder: MultiblockEntity) { + when (val present: InputData? = inputLocations.get(location)) { + is SingleMultiblockInput -> inputLocations[location] = SharedMultiblockInput.of(present.holder, holder) + is SharedMultiblockInput -> present.add(holder) + null -> inputLocations[location] = SingleMultiblockInput(holder) + } + + return + } + + fun remove(location: BlockKey, holder: MultiblockEntity) { + when (val present: InputData? = inputLocations.get(location)) { + is SingleMultiblockInput -> if (present.holder == holder) inputLocations.remove(location) + is SharedMultiblockInput -> present.remove(holder) + null -> return + } + } + + fun getAllHolders(location: BlockKey): Set { + return when (val present: InputData? = inputLocations.get(location)) { + is SingleMultiblockInput -> setOf(present.holder) + is SharedMultiblockInput -> present.getAllHolders() + null -> setOf() + } + } + + fun removeAll(location: BlockKey) { + inputLocations.remove(location) + } + + fun contains(location: BlockKey): Boolean { + return inputLocations.contains(location) + } + + sealed interface InputData { + fun contains(holder: MultiblockEntity): Boolean + } + + data class SingleMultiblockInput(val holder: MultiblockEntity) : InputData { + override fun contains(holder: MultiblockEntity): Boolean { + return this.holder == holder + } + } + + class SharedMultiblockInput : InputData { + private val holders: ObjectOpenHashSet = ObjectOpenHashSet() + + override fun contains(holder: MultiblockEntity): Boolean { + return holders.contains(holder) + } + + fun add(multiblockEntity: MultiblockEntity) { + holders.add(multiblockEntity) + } + + fun remove(multiblockEntity: MultiblockEntity) { + holders.remove(multiblockEntity) + } + + fun getAllHolders() = holders.clone() + + companion object { + fun of(vararg entities: MultiblockEntity): SharedMultiblockInput { + val new = SharedMultiblockInput() + entities.forEach(new::add) + return new + } + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/ShipInputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/ShipInputManager.kt new file mode 100644 index 0000000000..03dd655807 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/ShipInputManager.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.nodes.inputs + +import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager + +class ShipInputManager(val shipManager: ShipTransportManager) : InputManager() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputManager.kt new file mode 100644 index 0000000000..ef0b8f3cde --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputManager.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.nodes.inputs + +import net.horizonsend.ion.server.features.world.IonWorld + +class WorldInputManager(val world: IonWorld) : InputManager() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputs.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputs.kt new file mode 100644 index 0000000000..9ba6bdcbdc --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/WorldInputs.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.nodes.inputs + +object WorldInputs { + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 97ed76e279..ea46fc8b98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.manager.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship +import net.horizonsend.ion.server.features.transport.nodes.inputs.WorldInputManager import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.configuration.DefaultWorldConfiguration @@ -50,6 +51,7 @@ class IonWorld private constructor( val chunkRegions: MutableSet = ObjectOpenHashSet() val multiblockManager = WorldMultiblockManager(this) + val inputManager = WorldInputManager(this) /** * Gets the IonChunk at the specified coordinates if it is loaded @@ -126,10 +128,6 @@ class IonWorld private constructor( //TODO // - Terrain Generator // - Worldborder injection - // - World multiblock tracker - // - Area shields - // - Mob defenders - // - Base shields? companion object : IonServerComponent() { private val WORLD_CONFIGURATION_DIRECTORY = ConfigurationFiles.configurationFolder.resolve("worlds").apply { mkdirs() } From 0be6409670e3bdaa2d8d0a4918a218b95e08a9a1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 11 Nov 2024 13:32:21 -0600 Subject: [PATCH 271/500] Add input locations to multiblock classes, register / release them --- .../multiblock/entity/MultiblockEntity.kt | 17 +++++++++++++- .../entity/type/fluids/FluidStoringEntity.kt | 7 ++++++ .../type/power/PoweredMultiblockEntity.kt | 9 ++++++++ .../entity/type/power/SimplePoweredEntity.kt | 16 +++++++++++++ .../multiblock/manager/MultiblockManager.kt | 1 + .../type/fluid/ElectrolysisMultiblock.kt | 23 +++++++++++-------- .../collector/PipedGasCollectorMultiblock.kt | 18 +++++++-------- .../fluid/storage/FluidStorageMultiblock.kt | 19 ++++++++------- 8 files changed, 79 insertions(+), 31 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index a272eefac7..bb8477022c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -183,7 +184,7 @@ abstract class MultiblockEntity( return world.getBlockAt(x, y, z) } - fun getPosRelative(forward: Int, right: Int, up: Int): Vec3i { + fun getPosRelative(right: Int, up: Int, forward: Int): Vec3i { return getRelative(vec3i, structureDirection, right = right, up = up, forward = forward) } @@ -282,4 +283,18 @@ abstract class MultiblockEntity( fun markChanged() { manager.markChanged() } + + fun registerInputs(type: NetworkType, locations: Set) { + val inputManager = manager.getInputManager() + for (location in locations) { + inputManager.registerInput(type, toBlockKey(location), this) + } + } + + fun releaseInputs(type: NetworkType, locations: Set) { + val inputManager = manager.getInputManager() + for (location in locations) { + inputManager.deRegisterInput(type, toBlockKey(location), this) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index b69f886cca..7845c18391 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -16,6 +16,13 @@ import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { val capacities: Array + val fluidInputOffsets: Array + + fun getFluidInputLocations(): Set { + this as MultiblockEntity + return fluidInputOffsets.mapTo(mutableSetOf()) { (right, up, forward) -> getPosRelative(right, up, forward) } + } + /** * Returns whether any of the internal storages can store the amount of the fluid provided **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index 98e26bcbf0..b9edfbf17b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,13 +1,22 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { val powerStorage: PowerStorage val maxPower: Int + val powerInputOffsets: Array + + fun getPowerInputLocations(): Set { + this as MultiblockEntity + return powerInputOffsets.mapTo(mutableSetOf()) { (right, up, forward) -> getPosRelative(right, up, forward) } + } + fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), maxPower) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index 32b15968b0..bb41fe5e57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -8,7 +8,9 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext @@ -25,6 +27,8 @@ abstract class SimplePoweredEntity( structureDirection: BlockFace, final override val maxPower: Int ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { + override val powerInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) + @Suppress("LeakingThis") // Only a reference is needed, max power is provided in the constructor final override val powerStorage: PowerStorage = PowerStorage( this, @@ -40,4 +44,16 @@ abstract class SimplePoweredEntity( entity, PowerEntityDisplay(entity, +0.0, +0.0, +0.0, 0.5f) ).register() + + override fun onLoad() { + registerInputs(NetworkType.POWER, getPowerInputLocations()) + } + + override fun handleRemoval() { + releaseInputs(NetworkType.POWER, getPowerInputLocations()) + } + + override fun onUnload() { + releaseInputs(NetworkType.POWER, getPowerInputLocations()) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 73a7e68e65..75e1f8826e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -40,6 +40,7 @@ abstract class MultiblockManager(val log: Logger) { abstract fun getNetwork(type: NetworkType): TransportCache abstract fun getSignUnsavedTime(): Long + open fun markSignSaved() {} /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 5e9f4e2888..a1cebd5da0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.features.client.display.modular.display.fluid. import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.SingleFluidStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer @@ -25,10 +26,10 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 @@ -201,11 +202,14 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf() + override val powerInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) + override val powerStorage: PowerStorage = loadStoredPower(data) override val capacities: Array = arrayOf( @@ -218,7 +222,7 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf(Vec3i(0, -1, 0)) override val capacities: Array = arrayOf( loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), @@ -115,7 +117,7 @@ object PipedGasCollectorMultiblock : Multiblock(), loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), ) - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, SimpleFluidDisplay(getNamedStorage("tank_1"), +0.0, +0.10, 0.0, 0.45f), SimpleFluidDisplay(getNamedStorage("tank_2"), +0.0, -0.00, 0.0, 0.45f), @@ -123,19 +125,15 @@ object PipedGasCollectorMultiblock : Multiblock(), ).register() override fun onLoad() { - displayHandler.update() + registerInputs(NetworkType.FLUID, getFluidInputLocations()) } override fun onUnload() { - displayHandler.remove() + releaseInputs(NetworkType.FLUID, getFluidInputLocations()) } override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) + releaseInputs(NetworkType.FLUID, getFluidInputLocations()) } private val worldConfig get() = world.ion.configuration.gasConfiguration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index ff8f54e1c4..ff3a951aba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -5,12 +5,13 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SplitFluidDisplay import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.BasicFluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.UnlimitedInternalStorage import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -43,27 +44,25 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM z: Int, world: World, structureDirection: BlockFace, - ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity { + ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity, DisplayMultiblockEntity { override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) - private val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, SplitFluidDisplay(mainStorage, +0.0, -0.0, +0.0, 0.45f), ).register() + override val fluidInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) + override fun onLoad() { - displayHandler.update() + registerInputs(NetworkType.FLUID, getFluidInputLocations()) } override fun onUnload() { - displayHandler.remove() + releaseInputs(NetworkType.FLUID, getFluidInputLocations()) } override fun handleRemoval() { - displayHandler.remove() - } - - override fun displaceAdditional(movement: StarshipMovement) { - displayHandler.displace(movement) + releaseInputs(NetworkType.FLUID, getFluidInputLocations()) } override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { From 978f4c525eb1fa3ab3bd81f954afa6cef7204bd6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 11 Nov 2024 13:40:54 -0600 Subject: [PATCH 272/500] Debug command --- .../command/misc/TransportDebugCommand.kt | 17 +++++++++++++++++ .../transport/nodes/inputs/InputManager.kt | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 30c37fae90..9ec5e507f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -5,10 +5,16 @@ import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.old.Wires +import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.command.CommandSender +import org.bukkit.entity.Player import java.util.concurrent.Executors @CommandPermission("starlegacy.transportdebug") @@ -35,4 +41,15 @@ object TransportDebugCommand : SLCommand() { wireQueue.shutdownNow() Wires.thread = Executors.newSingleThreadExecutor(Wires.threadFactory) } + + @Subcommand("dump inputs") + fun dumpInputs(sender: Player, type: NetworkType) { + val inputManager = sender.world.ion.inputManager + val loc = Vec3i(sender.location) + val inputs = inputManager.getLocations(type) + .map { toVec3i(it) } + .filter { it.distance(loc) < 100.0 } + + sender.highlightBlocks(inputs, 50L) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt index dcb458df31..d2c8929dc8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt @@ -26,10 +26,12 @@ abstract class InputManager { return getTypeManager(type).getAllHolders(location) } + fun getLocations(type: NetworkType) = getTypeManager(type).getAllLocations() + class TypeManager(val manager: InputManager, val type: NetworkType) { private val inputLocations = Long2ObjectOpenHashMap() - fun getAll() = inputLocations.clone() + fun getAllLocations() = inputLocations.keys fun add(location: BlockKey, holder: MultiblockEntity) { when (val present: InputData? = inputLocations.get(location)) { From 21706fbc3bc56b897723aed13ac3409d0151e37c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 11 Nov 2024 13:44:21 -0600 Subject: [PATCH 273/500] move power cell input to the right spot --- .../multiblock/type/power/storage/PowerCellMultiblock.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 01c34410fd..c299821be3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.World import org.bukkit.block.BlockFace @@ -58,6 +59,7 @@ object PowerCellMultiblock : Multiblock(), EntityMultiblock = arrayOf(Vec3i(0, 0, 0)) override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) From 8b6858238418390bbfb8494692e27cf748ceb5aa Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 11 Nov 2024 14:01:23 -0600 Subject: [PATCH 274/500] get multis from input --- .../features/multiblock/MultiblockEntities.kt | 5 ++ .../nodes/cache/PowerTransportCache.kt | 47 ++++++++++++++----- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index aa7a596942..ac63f79dd9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -49,6 +49,11 @@ object MultiblockEntities : SLEventListener() { return getMultiblockEntity(origin.world, origin.x, origin.y, origin.z) } + fun getMultiblockEntity(sign: Sign): MultiblockEntity? { + val origin = MultiblockEntity.getOriginFromSign(sign) + return getMultiblockEntity(sign.world, origin.x, origin.y, origin.z) + } + /** * Add a new multiblock entity to the chunk **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 34e816afe5..49e1014005 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,16 +1,24 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerFlowMeter import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerInputNode -import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import org.bukkit.Axis import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD @@ -21,6 +29,7 @@ import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE import org.bukkit.World import org.bukkit.block.BlockFace +import org.bukkit.block.Sign import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod import java.util.concurrent.Future @@ -36,6 +45,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) .addDataHandler(OBSERVER) { PowerFlowMeter(it.facing) } + .addSimpleNode(OBSERVER, PowerInputNode) .build() sealed interface PowerNode : CachedNode { @@ -95,15 +105,11 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only } - data class PowerInputNode(val pos: BlockKey) : PowerNode { + data object PowerInputNode : PowerNode { override val pathfindingResistance: Double = 0.0 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) - - fun distributePower(toSend: Int): Int { - return 0 - } } } @@ -131,18 +137,37 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor // These methods are outside the class for speed +/** + * Gets the powered entities accessible from this location, assuming it is an input + **/ +fun getPoweredEntities(world: World, location: BlockKey): Set { + val inputManager = world.ion.inputManager + val registered = inputManager.getHolders(NetworkType.POWER, location) + val adjacentBlocks = ADJACENT_BLOCK_FACES.mapNotNull { + val block = getBlockIfLoaded(world, getX(location), getY(location), getZ(location)) ?: return@mapNotNull null + val adjacent = block.getRelativeIfLoaded(it)?.state as? Sign ?: return@mapNotNull null + MultiblockEntities.getMultiblockEntity(adjacent) + } + + return registered.plus(adjacentBlocks) +} + +fun distributePower(location: BlockKey, amount: Int): Int { + return 0 +} + fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(world, NetworkType.POWER, origin) { true } /** * Runs the power transfer from the source to the destinations. pending rewrite **/ -private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: CachedNode, destinations: List, availableTransferPower: Int): Int { +private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: CachedNode, destinations: List, availableTransferPower: Int): Int { if (destinations.isEmpty()) return availableTransferPower val numDestinations = destinations.size val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(world, NetworkType.POWER, sourceType, sourcePos, destinations[it].pos) + getIdealPath(world, NetworkType.POWER, sourceType, sourcePos, destinations[it]) }.getOrNull() } var maximumResistance: Double = -1.0 @@ -178,10 +203,10 @@ private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: Cach val share = shareFactor / shareFactorSum val idealSend = (availableTransferPower * share).roundToInt() - val toSend = minOf(idealSend, getRemainingCapacity(destination)) + val toSend = minOf(idealSend, getRemainingCapacity(/*TODO*/)) // Amount of power that didn't fit - val remainder = destination.distributePower(toSend) + val remainder = distributePower(destination, toSend) val realTaken = toSend - remainder remainingPower -= realTaken @@ -199,7 +224,7 @@ private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: Cach return remainingPower } -private fun getRemainingCapacity(destination: PowerInputNode): Int { +private fun getRemainingCapacity(): Int { return 0 // destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } } From cd38c103c3b878a6b4f2a59cd8fae0a15f942281 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 12 Nov 2024 00:58:33 -0600 Subject: [PATCH 275/500] debug commands --- .../server/command/admin/IonChunkCommand.kt | 127 ++++++++++++------ .../nodes/cache/PowerTransportCache.kt | 49 ++++--- .../transport/nodes/cache/TransportCache.kt | 2 - .../transport/util/NodePathfinding.kt | 12 +- 4 files changed, 123 insertions(+), 67 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index c6cb08e7f4..88a6c3f87a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,17 +4,26 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand +import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.getNextNodes import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text +import org.bukkit.block.BlockFace import org.bukkit.entity.Player @CommandAlias("ionchunk") @@ -129,7 +138,7 @@ object IonChunkCommand : SLCommand() { val grid = network.get(ionChunk) val key = toBlockKey(targeted.x, targeted.y, targeted.z) - sender.information("Targeted node: ${grid.getRawCache()[key]}") + sender.information("Targeted node: ${grid.getOrCache(key)}") } @Subcommand("test extractor") @@ -141,57 +150,89 @@ object IonChunkCommand : SLCommand() { val node = grid.getCached(key) if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) return - grid.tickExtractor(node) + grid.tickExtractor(key, sender.world) } @Subcommand("test pathfinding") fun onTestPathfinding(sender: Player) { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() -// val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager -// val key = toBlockKey(targeted.x, targeted.y, targeted.z) -// -// val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") -// val transferable = at.getTransferableNodes() - -// fun getNext(node: TransportNode): Collection { -// at as PowerPathfindingNode -// return at.getNextNodes(node, null) -// } -// -// sender.information("Transferable nodes from ${at.javaClass.simpleName}") -// sender.information(transferable.joinToString(separator = "\n") { next -> -// "${next.javaClass.simpleName} -> [${getNext(next).joinToString { it.javaClass.simpleName }}]" -// }) + val grid = NetworkType.POWER.get(ionChunk) as PowerTransportCache + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val at = grid.getOrCache(key) ?: return sender.userError("No node at $targeted") + val transferable = getNextNodes( + NetworkType.POWER, + sender.world, + backwards = BlockFace.SELF, + key, + at + ) + + fun getNext(dir: BlockFace): Collection { + return getNextNodes( + NetworkType.POWER, + sender.world, + backwards = dir.oppositeFace, + getRelative(key, dir), + at + ).values + } + + sender.information("Transferable nodes from ${at.javaClass.simpleName}") + sender.information(transferable.entries.joinToString(separator = "\n") { (offset, type) -> + "${type.javaClass.simpleName} -> [${getNext(offset).joinToString { it.javaClass.simpleName }}]" + }) } @Subcommand("test flood") fun onTestFloodFill(sender: Player) { -// val targeted = sender.getTargetBlock(null, 10) -// val ionChunk = targeted.chunk.ion() -// val grid = NetworkType.POWER.get(ionChunk) as PowerNodeManager -// val key = toBlockKey(targeted.x, targeted.y, targeted.z) -// -// val at = grid.nodes[key] ?: return sender.userError("No node at $targeted") -// -// val visitQueue = ArrayDeque() -// val visitedSet = ObjectOpenHashSet() -// val destinations = ObjectOpenHashSet() -// -// visitQueue.addAll(at.cachedTransferable) -// var iterations = 0L -// -// while (visitQueue.isNotEmpty()) { -// iterations++ -// val currentNode = visitQueue.removeFirst() -// Tasks.syncDelay(iterations) { sender.highlightBlock(currentNode.getCenter(), 5L) } -// visitedSet.add(currentNode) -// -// if (currentNode is PowerInputNode) { -// destinations.add(currentNode) -// } -// -// visitQueue.addAll(currentNode.cachedTransferable.filterNot { visitedSet.contains(it) }) -// } + val targeted = sender.getTargetBlock(null, 10) + val ionChunk = targeted.chunk.ion() + val grid = NetworkType.POWER.get(ionChunk) as PowerTransportCache + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val at = grid.getOrCache(key) ?: return sender.userError("No node at $targeted") + val visitQueue = ArrayDeque>() + val visitedSet = LongOpenHashSet() + val destinations = LongOpenHashSet() + + visitQueue.addAll(getNextNodes( + NetworkType.POWER, + sender.world, + BlockFace.SELF, + key, + at + ).toList().map { getRelative(key, it.first) to it.second }) + + println("Initial queue:") + println(visitQueue.toList()) + + var iterations = 0L + + while (visitQueue.isNotEmpty()) { + iterations++ + val (currentPos, currentType) = visitQueue.removeFirst() + Tasks.syncDelay(iterations) { sender.highlightBlock(toVec3i(currentPos), 5L) } + visitedSet.add(currentPos) + + println("Queue size: ${visitQueue.size}") + if (currentType is PowerInputNode) { + destinations.add(currentPos) + } + + val next = getNextNodes( + NetworkType.POWER, + sender.world, + BlockFace.SELF, + currentPos, + currentType + ).toList().map { getRelative(key, it.first) to it.second } + + println("next from $currentType: $next") + + visitQueue.addAll(next.filterNot { visitedSet.contains(it.first) }) + println("Queue size: ${visitQueue.size}") + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 49e1014005..444b84f3d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,7 +1,10 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerFlowMeter @@ -14,6 +17,7 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ @@ -113,30 +117,43 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor } } - fun tickExtractor(extractorNode: PowerNode.PowerExtractorNode): Future<*> = NewTransport.executor.submit { -// val source = extractorNode.getSourcePool().filterNot { it.powerStorage.isEmpty() }.randomOrNull() ?: return@submit -// -// val destinations: ObjectOpenHashSet = getPowerInputs(extractorNode) + fun tickExtractor(location: BlockKey, world: World): Future<*> = NewTransport.executor.submit { + val sources = getExtractorSourcePool(location, world).filterNot { it.powerStorage.isEmpty() } + val source = sources.randomOrNull() ?: return@submit + + val destinations: LongOpenHashSet = getPowerInputs(world, location) // destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) // -// if (destinations.isEmpty()) return@submit -// -// val transferred = minOf(source.powerStorage.getPower(), powerCheck) -// val notRemoved = source.powerStorage.removePower(transferred) -// val remainder = runPowerTransfer(extractorNode, destinations.toMutableList(), (transferred - notRemoved)) + if (destinations.isEmpty()) return@submit // -// if (transferred == remainder) { -// //TODO skip growing number of ticks if nothing to do -// } -// -// if (remainder > 0) { -// source.powerStorage.addPower(remainder) -// } + val transferred = minOf(source.powerStorage.getPower(), IonServer.transportSettings.maxPowerRemovedPerExtractorTick) + val notRemoved = source.powerStorage.removePower(transferred) + val remainder = runPowerTransfer( + world, + location, + PowerNode.PowerExtractorNode, + destinations.toMutableList(), + (transferred - notRemoved) + ) + + if (transferred == remainder) { + //TODO skip growing number of ticks if nothing to do + } + + if (remainder > 0) { + source.powerStorage.addPower(remainder) + } } } // These methods are outside the class for speed +fun getExtractorSourcePool(extractorLocation: BlockKey, world: World): List { + return ADJACENT_BLOCK_FACES.flatMap { + getPoweredEntities(world, getRelative(extractorLocation, it)) + }.filterIsInstance() +} + /** * Gets the powered entities accessible from this location, assuming it is an input **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index a0e045712c..70cadc119c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -39,9 +39,7 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network } fun cache(location: BlockKey, block: Block): CachedNode? { - println("Caching") val type = nodeFactory.cache(block) - println("Type: $type") val state = if (type == null) CacheState.Empty else CacheState.Present(type) cache[location] = state diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index cadb7bc975..a91397e6f1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -22,16 +22,16 @@ fun getOrCacheNode(type: NetworkType, world: World, pos: BlockKey): CachedNode? return type.get(chunk).getOrCache(pos) } -fun getNextNodes(networkType: NetworkType, world: World, backwards: BlockFace, parentPos: BlockKey, parentType: CachedNode): Map { +fun getNextNodes(networkType: NetworkType, world: World, backwards: BlockFace, currentPos: BlockKey, parentType: CachedNode?): Map { val adjacent = ADJACENT_BLOCK_FACES.minus(backwards) val map = mutableMapOf() for (adjacentFace in adjacent) { - val pos = getRelative(parentPos, adjacentFace) + val pos = getRelative(currentPos, adjacentFace) val cached = getOrCacheNode(networkType, world, pos) ?: continue - if (!cached.canTransferFrom(parentType, adjacentFace) || !parentType.canTransferTo(cached, adjacentFace)) continue + if (parentType != null && (!cached.canTransferFrom(parentType, adjacentFace) || !parentType.canTransferTo(cached, adjacentFace))) continue map[adjacentFace] = cached } @@ -50,7 +50,7 @@ inline fun getNetworkDestinations(world: World, networkT networkType = networkType, world = world, backwards = BlockFace.SELF, - parentPos = originPos, + currentPos = originPos, parentType = originNode ) @@ -68,7 +68,7 @@ inline fun getNetworkDestinations(world: World, networkT networkType = networkType, world = world, backwards = offset.oppositeFace, - parentPos = currentPos, + currentPos = currentPos, parentType = currentNode ).filterNot { visitedSet.contains(getRelative(currentPos, it.key)) }.map { Triple(it.key, getRelative(originPos, it.key), it.value) } @@ -149,7 +149,7 @@ fun getNeighbors(current: PathfindingNodeWrapper, audience: Audience? = null): A current.type, current.world, backwards = current.offset.oppositeFace, - parentPos = current.pos, + currentPos = current.pos, parentType = current.node ).toList() From 2905be5b989d9d5fa6ab1b16350e22d38c4b3b0b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 12 Nov 2024 12:16:21 -0600 Subject: [PATCH 276/500] Simplify pathfinding --- .../server/command/admin/IonChunkCommand.kt | 94 +++------------ .../custom/items/misc/MultimeterItem.kt | 26 ++--- .../transport/nodes/cache/CachedNode.kt | 35 ++++-- .../nodes/cache/PowerTransportCache.kt | 49 ++++---- .../transport/util/NodePathfinding.kt | 110 +++++------------- 5 files changed, 102 insertions(+), 212 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 88a6c3f87a..7b87208a63 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -4,26 +4,22 @@ import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand -import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.NetworkType -import net.horizonsend.ion.server.features.transport.util.getNextNodes +import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text -import org.bukkit.block.BlockFace import org.bukkit.entity.Player @CommandAlias("ionchunk") @@ -153,86 +149,22 @@ object IonChunkCommand : SLCommand() { grid.tickExtractor(key, sender.world) } - @Subcommand("test pathfinding") - fun onTestPathfinding(sender: Player) { - val targeted = sender.getTargetBlock(null, 10) - val ionChunk = targeted.chunk.ion() - val grid = NetworkType.POWER.get(ionChunk) as PowerTransportCache - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - val at = grid.getOrCache(key) ?: return sender.userError("No node at $targeted") - val transferable = getNextNodes( - NetworkType.POWER, - sender.world, - backwards = BlockFace.SELF, - key, - at - ) - - fun getNext(dir: BlockFace): Collection { - return getNextNodes( - NetworkType.POWER, - sender.world, - backwards = dir.oppositeFace, - getRelative(key, dir), - at - ).values - } - - sender.information("Transferable nodes from ${at.javaClass.simpleName}") - sender.information(transferable.entries.joinToString(separator = "\n") { (offset, type) -> - "${type.javaClass.simpleName} -> [${getNext(offset).joinToString { it.javaClass.simpleName }}]" - }) + @Subcommand("test flood") + fun onTestFloodFill(sender: Player, network: NetworkType) { + sender.information("Trying to find input nodes") + val (cached, location) = requireLookingAt(sender, network) + val destinations = getNetworkDestinations(NetworkType.POWER, sender.world, location) { true } + sender.information("${destinations.size} destinations") + sender.highlightBlocks(destinations.map(::toVec3i), 50L) } - @Subcommand("test flood") - fun onTestFloodFill(sender: Player) { + private fun requireLookingAt(sender: Player, network: NetworkType): Pair { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() - val grid = NetworkType.POWER.get(ionChunk) as PowerTransportCache + val grid = network.get(ionChunk) val key = toBlockKey(targeted.x, targeted.y, targeted.z) - val at = grid.getOrCache(key) ?: return sender.userError("No node at $targeted") - val visitQueue = ArrayDeque>() - val visitedSet = LongOpenHashSet() - val destinations = LongOpenHashSet() - - visitQueue.addAll(getNextNodes( - NetworkType.POWER, - sender.world, - BlockFace.SELF, - key, - at - ).toList().map { getRelative(key, it.first) to it.second }) - - println("Initial queue:") - println(visitQueue.toList()) - - var iterations = 0L - - while (visitQueue.isNotEmpty()) { - iterations++ - val (currentPos, currentType) = visitQueue.removeFirst() - Tasks.syncDelay(iterations) { sender.highlightBlock(toVec3i(currentPos), 5L) } - visitedSet.add(currentPos) - - println("Queue size: ${visitQueue.size}") - if (currentType is PowerInputNode) { - destinations.add(currentPos) - } - - val next = getNextNodes( - NetworkType.POWER, - sender.world, - BlockFace.SELF, - currentPos, - currentType - ).toList().map { getRelative(key, it.first) to it.second } - - println("next from $currentType: $next") - - visitQueue.addAll(next.filterNot { visitedSet.contains(it.first) }) - println("Queue size: ${visitQueue.size}") - } + val node = grid.getOrCache(key) ?: fail { "You aren't looking at a node!" } + return node to key } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 5261a606b2..55da6e3cfa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -91,7 +91,7 @@ object MultimeterItem : CustomItem("Multimeter") { val firstNode = networkType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") - val path = getIdealPath(world, networkType, audience, firstPoint, firstNode, secondPoint) + val path = getIdealPath(audience, CachedNode.NodePositionData(firstNode, world, firstPoint, BlockFace.SELF), secondPoint) val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${toVec3i(secondPoint)} at ${toVec3i(secondPoint)} is $resistance") } @@ -111,7 +111,7 @@ object MultimeterItem : CustomItem("Multimeter") { /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ - private fun getIdealPath(world: World, type: NetworkType, audience: Audience, fromPos: BlockKey, fromNode: CachedNode, toPos: BlockKey): Array? { + private fun getIdealPath(audience: Audience, fromNode: CachedNode.NodePositionData, toPos: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -127,18 +127,12 @@ object MultimeterItem : CustomItem("Multimeter") { queueSet.remove(wrapper.node.hashCode()) } - queueAdd( - PathfindingNodeWrapper( - world = world, - pos = fromPos, + queueAdd(PathfindingNodeWrapper( node = fromNode, parent = null, - offset = BlockFace.SELF, - type = type, g = 0, f = 0 - ) - ) + )) val visited = LongOpenHashSet() @@ -148,19 +142,19 @@ object MultimeterItem : CustomItem("Multimeter") { while (queue.isNotEmpty() && iterations < 150) { iterations++ val current = queue.minBy { it.f } - Tasks.syncDelay(iterations) { audience.highlightBlock(toVec3i(current.pos), 5L) } - audience.information("current: ${current.node.javaClass.simpleName} at ${toVec3i(current.pos)}") - if (current.pos == toPos) return current.buildPath() + Tasks.syncDelay(iterations) { audience.highlightBlock(toVec3i(current.node.position), 5L) } + audience.information("current: ${current.node.javaClass.simpleName} at ${toVec3i(current.node.position)}") + if (current.node.position == toPos) return current.buildPath() queueRemove(current) - visited.add(current.pos) + visited.add(current.node.position) val neighbors = getNeighbors(current, audience) if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { - audience.information("new neighbor: ${newNeighbor} at ${toVec3i(newNeighbor.pos)}") - if (visited.contains(newNeighbor.pos)) { + audience.information("new neighbor: ${newNeighbor} at ${toVec3i(newNeighbor.node.position)}") + if (visited.contains(newNeighbor.node.position)) { audience.information("conmtinue") continue } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt index e57ebf154b..2807a7e2e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt @@ -1,16 +1,17 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import org.bukkit.Material +import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.getOrCacheNode +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import org.bukkit.World import org.bukkit.block.BlockFace interface CachedNode { + val networkType: NetworkType val pathfindingResistance: Double - /** - * Gets the directions that should be checked for the next nodes - * - * Returns a map of block face to transfer priority - **/ - fun getNextNodes(inputDirection: BlockFace): Collection> + + fun getTransferableDirections(backwards: BlockFace): Set /** * Adds any restrictions on transferring to another node @@ -21,4 +22,24 @@ interface CachedNode { * Adds any restrictions on transferring from another node **/ fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean + + fun getNextNodes(world: World, position: BlockKey, backwards: BlockFace): List { + val adjacent = getTransferableDirections(backwards) + val nodes = mutableListOf() + + for (adjacentFace in adjacent) { + val pos = getRelative(position, adjacentFace) + val cached = getOrCacheNode(networkType, world, pos) ?: continue + + if (!cached.canTransferFrom(this, adjacentFace) || !canTransferTo(cached, adjacentFace)) continue + + nodes.add(NodePositionData(cached, world, getRelative(position, adjacentFace), adjacentFace)) + } + + return nodes + } + + data class NodePositionData(val type: CachedNode, val world: World, val position: BlockKey, val offset: BlockFace) { + fun getNextNodes(): List = type.getNextNodes(world, position, offset.oppositeFace) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 444b84f3d5..fd0df2cafa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -28,6 +28,7 @@ import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD import org.bukkit.Material.IRON_BLOCK import org.bukkit.Material.LAPIS_BLOCK +import org.bukkit.Material.NOTE_BLOCK import org.bukkit.Material.OBSERVER import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE @@ -49,51 +50,45 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) .addDataHandler(OBSERVER) { PowerFlowMeter(it.facing) } - .addSimpleNode(OBSERVER, PowerInputNode) + .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() sealed interface PowerNode : CachedNode { - fun anyDirection(inputDirection: BlockFace) = ADJACENT_BLOCK_FACES.minus(inputDirection.oppositeFace).map { it to 1 } + override val networkType: NetworkType get() = NetworkType.POWER data object SpongeNode : PowerNode { override val pathfindingResistance: Double = 1.0 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } data class EndRodNode(val axis: Axis) : PowerNode { override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false - override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis + override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) } data object PowerExtractorNode : PowerNode { override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = false - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) + override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is PowerInputNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } data object PowerMergeNode : PowerNode { override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is SpongeNode override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is SpongeNode - override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf( - inputDirection to 10, - *ADJACENT_BLOCK_FACES.minus(inputDirection).minus(inputDirection.oppositeFace).map { it to 1 }.toTypedArray() - ) + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } data object PowerInvertedMergeNode : PowerNode { override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is EndRodNode override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is EndRodNode - override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf( - inputDirection to 10, - *ADJACENT_BLOCK_FACES.minus(inputDirection).minus(inputDirection.oppositeFace).map { it to 1 }.toTypedArray() - ) + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } data class PowerFlowMeter(val face: BlockFace) : PowerNode { @@ -106,14 +101,14 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun getNextNodes(inputDirection: BlockFace): Collection> = listOf(inputDirection to 1) // Forward only + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } data object PowerInputNode : PowerNode { override val pathfindingResistance: Double = 0.0 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false - override fun getNextNodes(inputDirection: BlockFace): Collection> = anyDirection(inputDirection) + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } } @@ -129,9 +124,12 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor val transferred = minOf(source.powerStorage.getPower(), IonServer.transportSettings.maxPowerRemovedPerExtractorTick) val notRemoved = source.powerStorage.removePower(transferred) val remainder = runPowerTransfer( - world, - location, - PowerNode.PowerExtractorNode, + CachedNode.NodePositionData( + PowerNode.PowerExtractorNode, + world, + location, + BlockFace.SELF + ), destinations.toMutableList(), (transferred - notRemoved) ) @@ -147,7 +145,6 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor } // These methods are outside the class for speed - fun getExtractorSourcePool(extractorLocation: BlockKey, world: World): List { return ADJACENT_BLOCK_FACES.flatMap { getPoweredEntities(world, getRelative(extractorLocation, it)) @@ -173,18 +170,18 @@ fun distributePower(location: BlockKey, amount: Int): Int { return 0 } -fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(world, NetworkType.POWER, origin) { true } +fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(NetworkType.POWER, world, origin) { true } /** * Runs the power transfer from the source to the destinations. pending rewrite **/ -private fun runPowerTransfer(world: World, sourcePos: BlockKey, sourceType: CachedNode, destinations: List, availableTransferPower: Int): Int { +private fun runPowerTransfer(source: CachedNode.NodePositionData, destinations: List, availableTransferPower: Int): Int { if (destinations.isEmpty()) return availableTransferPower val numDestinations = destinations.size - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(world, NetworkType.POWER, sourceType, sourcePos, destinations[it]) + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(source, destinations[it]) }.getOrNull() } var maximumResistance: Double = -1.0 @@ -245,7 +242,7 @@ private fun getRemainingCapacity(): Int { return 0 // destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } } -private fun completeChain(path: Array?, transferred: Int) { +private fun completeChain(path: Array?, transferred: Int) { path?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(transferred) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index a91397e6f1..6256d613d0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -5,9 +5,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -22,55 +20,28 @@ fun getOrCacheNode(type: NetworkType, world: World, pos: BlockKey): CachedNode? return type.get(chunk).getOrCache(pos) } -fun getNextNodes(networkType: NetworkType, world: World, backwards: BlockFace, currentPos: BlockKey, parentType: CachedNode?): Map { - val adjacent = ADJACENT_BLOCK_FACES.minus(backwards) - - val map = mutableMapOf() - - for (adjacentFace in adjacent) { - val pos = getRelative(currentPos, adjacentFace) - val cached = getOrCacheNode(networkType, world, pos) ?: continue - - if (parentType != null && (!cached.canTransferFrom(parentType, adjacentFace) || !parentType.canTransferTo(cached, adjacentFace))) continue - - map[adjacentFace] = cached - } - - return map -} - -inline fun getNetworkDestinations(world: World, networkType: NetworkType, originPos: BlockKey, check: (T) -> Boolean): LongOpenHashSet { +inline fun getNetworkDestinations(networkType: NetworkType, world: World, originPos: BlockKey, check: (CachedNode.NodePositionData) -> Boolean): LongOpenHashSet { val originNode = getOrCacheNode(networkType, world, originPos) ?: return LongOpenHashSet() - val visitQueue = ArrayDeque>() + val visitQueue = ArrayDeque() val visitedSet = LongOpenHashSet() val destinations = LongOpenHashSet() - val immediate = getNextNodes( - networkType = networkType, + visitQueue.addAll(originNode.getNextNodes( world = world, - backwards = BlockFace.SELF, - currentPos = originPos, - parentType = originNode - ) - - visitQueue.addAll(immediate.map { Triple(it.key, getRelative(originPos, it.key), it.value) }) + position = originPos, + backwards = BlockFace.SELF + )) while (visitQueue.isNotEmpty()) { - val (offset, currentPos, currentNode) = visitQueue.removeFirst() - visitedSet.add(currentPos) + val current = visitQueue.removeFirst() + visitedSet.add(current.position) - if (currentNode is T && check(currentNode)) { - destinations.add(currentPos) + if (current.type is T && check(current)) { + destinations.add(current.position) } - val next = getNextNodes( - networkType = networkType, - world = world, - backwards = offset.oppositeFace, - currentPos = currentPos, - parentType = currentNode - ).filterNot { visitedSet.contains(getRelative(currentPos, it.key)) }.map { Triple(it.key, getRelative(originPos, it.key), it.value) } + val next = current.getNextNodes().filterNot { visitedSet.contains(it.position) || visitQueue.contains(it) } visitQueue.addAll(next) } @@ -81,7 +52,7 @@ inline fun getNetworkDestinations(world: World, networkT /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ -fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: BlockKey, to: BlockKey): Array? { +fun getIdealPath(from: CachedNode.NodePositionData, to: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -89,26 +60,20 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: fun queueAdd(wrapper: PathfindingNodeWrapper) { queue.add(wrapper) - queueSet.add(wrapper.pos) + queueSet.add(wrapper.node.position) } fun queueRemove(wrapper: PathfindingNodeWrapper) { queue.remove(wrapper) - queueSet.remove(wrapper.pos) + queueSet.remove(wrapper.node.position) } - queueAdd( - PathfindingNodeWrapper( - world = world, - pos = fromPos, - node = fromType, + queueAdd(PathfindingNodeWrapper( + node = from, parent = null, - offset = BlockFace.SELF, - type = type, g = 0, f = 0 - ) - ) + )) val visited = IntOpenHashSet() @@ -119,7 +84,7 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: iterations++ val current = queue.minBy { it.f } - if (current.pos == to) return current.buildPath() + if (current.node.position == to) return current.buildPath() queueRemove(current) visited.add(current.node.hashCode()) @@ -128,7 +93,7 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: if (visited.contains(neighbor.node.hashCode())) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) - if (queueSet.contains(neighbor.pos)) { + if (queueSet.contains(neighbor.node.position)) { val existingNeighbor = queue.first { it.node === neighbor.node } if (neighbor.g < existingNeighbor.g) { existingNeighbor.g = neighbor.g @@ -145,27 +110,16 @@ fun getIdealPath(world: World, type: NetworkType, fromType: CachedNode, fromPos: // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution fun getNeighbors(current: PathfindingNodeWrapper, audience: Audience? = null): Array { - val transferable = getNextNodes( - current.type, - current.world, - backwards = current.offset.oppositeFace, - currentPos = current.pos, - parentType = current.node - ).toList() + val transferable = current.node.getNextNodes().toList() audience?.information("${transferable.size} transferable nodes") return Array(transferable.size) { - val (neighborFace, neighborType) = transferable[it] - val neighborPos = getRelative(current.pos, neighborFace) + val next = transferable[it] PathfindingNodeWrapper( - world = current.world, - pos = neighborPos, - node = neighborType, + node = next, parent = current, - type = current.type, - offset = neighborFace, g = current.g + 1, f = 1 ) @@ -175,30 +129,22 @@ fun getNeighbors(current: PathfindingNodeWrapper, audience: Audience? = null): A // The heuristic used for the algorithm in this case is the distance from the node to the destination, which is typical, // But it also includes the pathfinding resistance to try to find the least resistant path. fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: BlockKey): Int { - val resistance = wrapper.node.pathfindingResistance - return (toVec3i(wrapper.pos).distance(toVec3i(destination)) + resistance).roundToInt() + val resistance = wrapper.node.type.pathfindingResistance + return (toVec3i(wrapper.node.position).distance(toVec3i(destination)) + resistance).roundToInt() } /** - * @param pos The position of this node in the path * @param node The cached node at this position * @param parent The parent node - * @param offset The offset direction between the parent and this node **/ data class PathfindingNodeWrapper( - val world: World, - val pos: BlockKey, - val node: CachedNode, - val type: NetworkType, + val node: CachedNode.NodePositionData, var parent: PathfindingNodeWrapper?, - var offset: BlockFace, var g: Int, var f: Int ) { - val network get() = IonChunk.getFromWorldCoordinates(world, getX(pos), getZ(pos))?.let { type.get(it) } - // Compiles the path - fun buildPath(): Array { + fun buildPath(): Array { val list = mutableListOf(this.node) var current: PathfindingNodeWrapper? = this @@ -235,6 +181,6 @@ data class PathfindingNodeWrapper( // } -fun calculatePathResistance(path: Array?): Double? { - return path?.sumOf { it.pathfindingResistance } +fun calculatePathResistance(path: Array?): Double? { + return path?.sumOf { it.type.pathfindingResistance } } From 05f33f747565902e296043d956fde15802b78f9e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 12 Nov 2024 13:06:20 -0600 Subject: [PATCH 277/500] Get powered entities from input manager --- .../nodes/cache/PowerTransportCache.kt | 33 ++++++++++--------- .../transport/nodes/inputs/InputManager.kt | 20 ++++++++--- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index fd0df2cafa..e8b229ad14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -109,20 +109,23 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(NetworkType.POWER, location).filterIsInstance() } } fun tickExtractor(location: BlockKey, world: World): Future<*> = NewTransport.executor.submit { val sources = getExtractorSourcePool(location, world).filterNot { it.powerStorage.isEmpty() } - val source = sources.randomOrNull() ?: return@submit + val source = sources.randomOrNull() ?: return@submit //TODO take from all + + val destinations: LongOpenHashSet = getNetworkDestinations(NetworkType.POWER, world, location) { + world.ion.inputManager.getHolders(type, it.position).isNotEmpty() + } - val destinations: LongOpenHashSet = getPowerInputs(world, location) -// destinations.removeAll(extractorNode.getTransferableNodes().filterIsInstanceTo(ObjectOpenHashSet())) -// if (destinations.isEmpty()) return@submit -// + val transferred = minOf(source.powerStorage.getPower(), IonServer.transportSettings.maxPowerRemovedPerExtractorTick) val notRemoved = source.powerStorage.removePower(transferred) + val remainder = runPowerTransfer( CachedNode.NodePositionData( PowerNode.PowerExtractorNode, @@ -134,9 +137,9 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor (transferred - notRemoved) ) - if (transferred == remainder) { - //TODO skip growing number of ticks if nothing to do - } +// if (transferred == remainder) { +// TODO skip growing number of ticks if nothing to do +// } if (remainder > 0) { source.powerStorage.addPower(remainder) @@ -166,12 +169,10 @@ fun getPoweredEntities(world: World, location: BlockKey): Set return registered.plus(adjacentBlocks) } -fun distributePower(location: BlockKey, amount: Int): Int { +fun distributePower(destinations: List, amount: Int): Int { return 0 } -fun getPowerInputs(world: World, origin: BlockKey) = getNetworkDestinations(NetworkType.POWER, world, origin) { true } - /** * Runs the power transfer from the source to the destinations. pending rewrite **/ @@ -214,13 +215,15 @@ private fun runPowerTransfer(source: CachedNode.NodePositionData, destinations: for ((index, destination) in destinations.withIndex()) { val shareFactor = shareFactors[index] ?: continue + val inputData = PowerInputNode.getPoweredEntities(source.world, destination) + val share = shareFactor / shareFactorSum val idealSend = (availableTransferPower * share).roundToInt() - val toSend = minOf(idealSend, getRemainingCapacity(/*TODO*/)) + val toSend = minOf(idealSend, getRemainingCapacity(inputData)) // Amount of power that didn't fit - val remainder = distributePower(destination, toSend) + val remainder = distributePower(inputData, toSend) val realTaken = toSend - remainder remainingPower -= realTaken @@ -238,8 +241,8 @@ private fun runPowerTransfer(source: CachedNode.NodePositionData, destinations: return remainingPower } -private fun getRemainingCapacity(): Int { - return 0 // destination.getPoweredEntities().sumOf { it.powerStorage.getRemainingCapacity() } +private fun getRemainingCapacity(destinations: List): Int { + return destinations.sumOf { it.powerStorage.getRemainingCapacity() } } private fun completeChain(path: Array?, transferred: Int) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt index d2c8929dc8..4cf03c710d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt @@ -26,6 +26,9 @@ abstract class InputManager { return getTypeManager(type).getAllHolders(location) } + fun getInputData(type: NetworkType, location: BlockKey): TypeManager.InputData? = + getTypeManager(type).getRaw(location) + fun getLocations(type: NetworkType) = getTypeManager(type).getAllLocations() class TypeManager(val manager: InputManager, val type: NetworkType) { @@ -33,6 +36,8 @@ abstract class InputManager { fun getAllLocations() = inputLocations.keys + fun getRaw(location: BlockKey): InputData? = inputLocations[location] + fun add(location: BlockKey, holder: MultiblockEntity) { when (val present: InputData? = inputLocations.get(location)) { is SingleMultiblockInput -> inputLocations[location] = SharedMultiblockInput.of(present.holder, holder) @@ -52,11 +57,7 @@ abstract class InputManager { } fun getAllHolders(location: BlockKey): Set { - return when (val present: InputData? = inputLocations.get(location)) { - is SingleMultiblockInput -> setOf(present.holder) - is SharedMultiblockInput -> present.getAllHolders() - null -> setOf() - } + return inputLocations.get(location)?.getHolders() ?: setOf() } fun removeAll(location: BlockKey) { @@ -69,12 +70,17 @@ abstract class InputManager { sealed interface InputData { fun contains(holder: MultiblockEntity): Boolean + fun getHolders(): Set } data class SingleMultiblockInput(val holder: MultiblockEntity) : InputData { override fun contains(holder: MultiblockEntity): Boolean { return this.holder == holder } + + override fun getHolders(): Set { + return setOf(holder) + } } class SharedMultiblockInput : InputData { @@ -84,6 +90,10 @@ abstract class InputManager { return holders.contains(holder) } + override fun getHolders(): Set { + return holders + } + fun add(multiblockEntity: MultiblockEntity) { holders.add(multiblockEntity) } From 608f98e1ccbf683683188e95131a4badc1748aed Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 12 Nov 2024 13:46:24 -0600 Subject: [PATCH 278/500] Get transfer working --- .../server/command/admin/IonChunkCommand.kt | 24 +++++++-------- .../nodes/cache/PowerTransportCache.kt | 30 +++++++++++++++++-- .../transport/util/NodePathfinding.kt | 3 +- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 7b87208a63..b28989be30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -15,8 +15,11 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportC import net.horizonsend.ion.server.features.transport.util.NetworkType import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component.text @@ -129,24 +132,17 @@ object IonChunkCommand : SLCommand() { @Subcommand("get node look") fun getNode(sender: Player, network: NetworkType) { - val targeted = sender.getTargetBlock(null, 10) - val ionChunk = targeted.chunk.ion() - val grid = network.get(ionChunk) - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - sender.information("Targeted node: ${grid.getOrCache(key)}") + val (node, location) = requireLookingAt(sender, network) + sender.information("Targeted node: $node at ${toVec3i(location)}") } @Subcommand("test extractor") fun onTick(sender: Player) { - val targeted = sender.getTargetBlock(null, 10) - val ionChunk = targeted.chunk.ion() - val grid = NetworkType.POWER.get(ionChunk) as PowerTransportCache - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - val node = grid.getCached(key) - if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) return - grid.tickExtractor(key, sender.world) + val (node, location) = requireLookingAt(sender, NetworkType.POWER) + if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) fail { "Extractor not targeted" } + val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } + val grid = NetworkType.POWER.get(chunk) as PowerTransportCache + grid.tickExtractor(location, sender.world) } @Subcommand("test flood") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index e8b229ad14..72c830caa4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -169,8 +169,34 @@ fun getPoweredEntities(world: World, location: BlockKey): Set return registered.plus(adjacentBlocks) } -fun distributePower(destinations: List, amount: Int): Int { - return 0 +fun distributePower(destinations: List, power: Int): Int { + val entities = destinations.filterTo(mutableListOf()) { !it.powerStorage.isFull() } + if (entities.isEmpty()) return power + + // Skip math for most scenarios + if (entities.size == 1) return entities.first().powerStorage.addPower(power) + + var remainingPower = power + + while (remainingPower > 0) { + if (entities.isEmpty()) break + + val share = remainingPower / entities.size + val minRemaining = entities.minOf { it.powerStorage.getRemainingCapacity() } + val distributed = minOf(minRemaining, share) + + val iterator = entities.iterator() + while (iterator.hasNext()) { + val entity = iterator.next() + + val r = entity.powerStorage.addPower(distributed) + if (entity.powerStorage.isFull()) iterator.remove() + + remainingPower -= (distributed - r) + } + } + + return remainingPower } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 6256d613d0..6b3b2e653a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -104,7 +104,6 @@ fun getIdealPath(from: CachedNode.NodePositionData, to: BlockKey): Array Date: Tue, 12 Nov 2024 14:13:19 -0600 Subject: [PATCH 279/500] tick extractors --- .../ion/server/command/admin/IonChunkCommand.kt | 2 +- .../server/features/transport/manager/TransportManager.kt | 3 ++- .../features/transport/nodes/cache/FluidTransportCache.kt | 5 +++++ .../features/transport/nodes/cache/PowerTransportCache.kt | 6 +++--- .../features/transport/nodes/cache/TransportCache.kt | 8 ++++++++ .../ion/server/features/world/chunk/IonChunk.kt | 4 +++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index b28989be30..ba18ee365d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -142,7 +142,7 @@ object IonChunkCommand : SLCommand() { if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) fail { "Extractor not targeted" } val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } val grid = NetworkType.POWER.get(chunk) as PowerTransportCache - grid.tickExtractor(location, sender.world) + grid.tickExtractor(location) } @Subcommand("test flood") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 65a56f1497..92ff1f3d4e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -14,6 +14,7 @@ abstract class TransportManager { abstract fun getInputProvider(): InputManager fun tick() { - + powerNodeManager.network.tick() + fluidNodeManager.network.tick() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index ad835f9a95..6d94a14c0f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -2,9 +2,14 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey class FluidTransportCache(holder: NetworkHolder): TransportCache(holder) { override val type: NetworkType = NetworkType.FLUID override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .build() + + override fun tickExtractor(location: BlockKey) { + + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 72c830caa4..1025fc2fa4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -37,7 +37,6 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod -import java.util.concurrent.Future import kotlin.math.roundToInt class PowerTransportCache(holder: NetworkHolder) : TransportCache(holder) { @@ -113,7 +112,8 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor } } - fun tickExtractor(location: BlockKey, world: World): Future<*> = NewTransport.executor.submit { + override fun tickExtractor(location: BlockKey) { NewTransport.executor.submit { + val world = holder.getWorld() val sources = getExtractorSourcePool(location, world).filterNot { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all @@ -144,7 +144,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor if (remainder > 0) { source.powerStorage.addPower(remainder) } - } + }} } // These methods are outside the class for speed diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 70cadc119c..d4a73264f1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -17,6 +17,14 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network abstract val type: NetworkType abstract val nodeFactory: NodeCacheFactory + fun tick() { + for (extractor in holder.getExtractorManager().getExtractors()) { + tickExtractor(extractor) + } + } + + abstract fun tickExtractor(location: BlockKey) + fun isCached(at: BlockKey): Boolean = cache.containsKey(at) fun getCached(at: BlockKey): CachedNode? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 9e912310e6..a9f832a5e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -81,7 +81,9 @@ class IonChunk( /** * Logic upon world tick **/ - fun tick() {} + fun tick() { + transportNetwork.tick() + } /** * Gets the neighboring chunk in this direction From d5fb2bdff962917cc1159eb6a83417e152edd2c9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 11:04:46 -0600 Subject: [PATCH 280/500] Provide block key to cache --- .../transport/nodes/cache/NodeCacheFactory.kt | 14 ++++++++------ .../transport/nodes/cache/PowerTransportCache.kt | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 0874c3db01..f02b4017a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe import org.bukkit.Material @@ -14,19 +16,19 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map>() - inline fun addDataHandler(material: Material, noinline constructor: (T) -> CachedNode): Builder { + inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> CachedNode): Builder { this.materialHandlers[material] = MaterialHandler(T::class, constructor) return this } fun addSimpleNode(material: Material, node: CachedNode): Builder { - this.materialHandlers[material] = MaterialHandler(BlockData::class) { node } + this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } return this } @@ -35,10 +37,10 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val blockDataClass: KClass, val constructor: (T) -> CachedNode) { - fun construct(blockData: BlockData): CachedNode { + class MaterialHandler(val blockDataClass: KClass, val constructor: (T, BlockKey) -> CachedNode) { + fun construct(blockData: BlockData, key: BlockKey): CachedNode { @Suppress("UNCHECKED_CAST") - return constructor.invoke(blockData as T) + return constructor.invoke(blockData as T, key) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 1025fc2fa4..9b6e7bc179 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -44,11 +44,11 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) .addSimpleNode(SPONGE, PowerNode.SpongeNode) - .addDataHandler(END_ROD) { PowerNode.EndRodNode(it.facing.axis) } + .addDataHandler(END_ROD) { data, _ -> PowerNode.EndRodNode(data.facing.axis) } .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) - .addDataHandler(OBSERVER) { PowerFlowMeter(it.facing) } + .addDataHandler(OBSERVER) { data, _ -> PowerFlowMeter(data.facing) } .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() From a75e39289152a06ccf9dd64f9a318e4b9755e401 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 11:05:57 -0600 Subject: [PATCH 281/500] give flow meter key --- .../features/transport/nodes/cache/PowerTransportCache.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 9b6e7bc179..ab2c27004a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -48,7 +48,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) - .addDataHandler(OBSERVER) { data, _ -> PowerFlowMeter(data.facing) } + .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(data.facing, loc) } .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() @@ -90,7 +90,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - data class PowerFlowMeter(val face: BlockFace) : PowerNode { + data class PowerFlowMeter(val face: BlockFace, val location: BlockKey) : PowerNode { //TODO display fun onCompleteChain(transferred: Int) { From 477c4a2df47cfc514a7dcd32c1d420b9b44f359a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 11:13:54 -0600 Subject: [PATCH 282/500] Add util functions to cached nodes --- .../features/transport/nodes/cache/CachedNode.kt | 2 ++ .../transport/nodes/cache/ComplexCachedNode.kt | 7 +++++++ .../transport/nodes/cache/PowerTransportCache.kt | 14 ++++++++++++-- .../transport/nodes/cache/TransportCache.kt | 4 ++-- 4 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt index 2807a7e2e4..fea29d208f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt @@ -42,4 +42,6 @@ interface CachedNode { data class NodePositionData(val type: CachedNode, val world: World, val position: BlockKey, val offset: BlockFace) { fun getNextNodes(): List = type.getNextNodes(world, position, offset.oppositeFace) } + + fun onInvalidate() {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt new file mode 100644 index 0000000000..ec2ea916ff --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.nodes.cache + +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement + +interface ComplexCachedNode { + fun onTranslate(movement: StarshipMovement) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index ab2c27004a..986631e150 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerFlowMeter @@ -21,6 +22,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.faces import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import org.bukkit.Axis @@ -62,11 +64,14 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - data class EndRodNode(val axis: Axis) : PowerNode { + data class EndRodNode(var axis: Axis) : PowerNode, ComplexCachedNode { override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) + override fun onTranslate(movement: StarshipMovement) { + this.axis = movement.displaceFace(this.axis.faces.first).axis + } } data object PowerExtractorNode : PowerNode { @@ -90,7 +95,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - data class PowerFlowMeter(val face: BlockFace, val location: BlockKey) : PowerNode { + data class PowerFlowMeter(var face: BlockFace, val location: BlockKey) : PowerNode, ComplexCachedNode { //TODO display fun onCompleteChain(transferred: Int) { @@ -101,6 +106,11 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override fun onTranslate(movement: StarshipMovement) { + this.face = movement.displaceFace(this.face) + //TODO rotate / move display + } } data object PowerInputNode : PowerNode { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index d4a73264f1..24a2dd21a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -55,11 +55,11 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network } fun invalidate(x: Int, y: Int, z: Int) { - return invalidate(toBlockKey(x, y, z)) + invalidate(toBlockKey(x, y, z)) } fun invalidate(key: BlockKey) { - cache.remove(key) + (cache.remove(key) as? CacheState.Present)?.node?.onInvalidate() } fun getRawCache() = cache From aa1df55e4869b064657ea2df7066fd0255a9f53c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 11:40:50 -0600 Subject: [PATCH 283/500] Add display back to power flow meter --- .../modular/display/FlowMeterDisplay.kt | 13 +++- .../nodes/cache/PowerTransportCache.kt | 64 +++++++++++++++++-- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index d5f45e3a60..43e3c39fbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -1,7 +1,13 @@ package net.horizonsend.ion.server.features.client.display.modular.display +import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.newline +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN +import net.kyori.adventure.text.format.NamedTextColor.YELLOW class FlowMeterDisplay( private val meter: PowerTransportCache.PowerNode.PowerFlowMeter, @@ -14,6 +20,11 @@ class FlowMeterDisplay( override fun deRegister() {} override fun getText(): Component { - return Component.text("0") + return meter.formatFlow() + } + + companion object { + val firstLine = text("E: ", YELLOW) + val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Sec", GREEN)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 986631e150..6b4896e20d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,7 +1,11 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity @@ -22,9 +26,13 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.faces import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN import org.bukkit.Axis import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD @@ -50,7 +58,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) - .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(data.facing, loc) } + .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(this, data.facing, loc) } .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() @@ -95,11 +103,55 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - data class PowerFlowMeter(var face: BlockFace, val location: BlockKey) : PowerNode, ComplexCachedNode { - //TODO display + data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexCachedNode { + val displayHandler = DisplayHandlers.newBlockOverlay( + cache.holder.getWorld(), + toVec3i(location), + face, + FlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) + ).register() + + private val STORED_AVERAGES = 20 + private val averages = mutableListOf() fun onCompleteChain(transferred: Int) { + addTransferred(TransferredPower(transferred, System.currentTimeMillis())) + displayHandler.update() + } + + private fun addTransferred(transferredSnapshot: TransferredPower) { + val currentSize = averages.size + + if (currentSize < STORED_AVERAGES) { + averages.add(transferredSnapshot) + return + } + + // If it is full, shift all averages to the right + for (index in 18 downTo 0) { + averages[index + 1] = averages[index] + } + + averages[0] = transferredSnapshot + } + private fun calculateAverage(): Double { + val sum = averages.sumOf { it.transferred } + + val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 + + return sum / timeDiff + } + + fun formatFlow(): Component { + var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) + + // If no averages, or no power has been moved in 5 seconds, go to 0 + if (averages.isEmpty() || System.currentTimeMillis() - averages.maxOf { it.time } > 5000) { + avg = 0.0 + } + + return ofChildren(FlowMeterDisplay.firstLine, text(avg, GREEN), FlowMeterDisplay.secondLine) } override val pathfindingResistance: Double = 0.5 @@ -109,8 +161,10 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun onTranslate(movement: StarshipMovement) { this.face = movement.displaceFace(this.face) - //TODO rotate / move display + displayHandler.displace(movement) } + + private data class TransferredPower(val transferred: Int, val time: Long) } data object PowerInputNode : PowerNode { @@ -282,7 +336,7 @@ private fun getRemainingCapacity(destinations: List): I } private fun completeChain(path: Array?, transferred: Int) { - path?.filterIsInstance(PowerFlowMeter::class.java)?.forEach { it.onCompleteChain(transferred) } + path?.forEach { if (it.type is PowerFlowMeter) it.type.onCompleteChain(transferred) } } // I hate this function but it works From 2e000f34e457a96be9a220a0c430bb560ac1c347 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 12:07:30 -0600 Subject: [PATCH 284/500] Give extractors metadata, reimplement transfer delta --- .../server/command/admin/IonChunkCommand.kt | 6 ++--- .../server/features/transport/NewTransport.kt | 2 +- .../transport/TransportConfiguration.kt | 11 ++++++--- .../transport/manager/TransportManager.kt | 7 ++++-- .../extractors/ChunkExtractorManager.kt | 19 +++++++-------- .../manager/extractors/ExtractorManager.kt | 23 ++++++++++++++++--- .../extractors/ShipExtractorManager.kt | 17 +++++++------- .../nodes/cache/FluidTransportCache.kt | 2 +- .../nodes/cache/PowerTransportCache.kt | 5 ++-- .../transport/nodes/cache/TransportCache.kt | 8 +------ 10 files changed, 61 insertions(+), 39 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index ba18ee365d..d085a87fdb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -91,8 +91,8 @@ object IonChunkCommand : SLCommand() { sender.information("${extractors.getExtractors().size} covered position(s).") - extractors.getExtractors().forEach { pos -> - sender.highlightBlock(toVec3i(pos), 50L) + extractors.getExtractors().forEach { extractor -> + sender.highlightBlock(toVec3i(extractor.pos), 50L) } } @@ -142,7 +142,7 @@ object IonChunkCommand : SLCommand() { if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) fail { "Extractor not targeted" } val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } val grid = NetworkType.POWER.get(chunk) as PowerTransportCache - grid.tickExtractor(location) + grid.tickExtractor(location, 1.0) } @Subcommand("test flood") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index d103c5a06e..66a17d758d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -32,7 +32,7 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t override fun onEnable() { executor = Executors.newFixedThreadPool(64, Tasks.namedThreadFactory("wire-transport")) - val interval: Long = IonServer.transportSettings.extractorTickIntervalMS + val interval: Long = IonServer.transportSettings.extractorConfiguration.extractorTickIntervalMS monitorThread = fixedRateTimer(name = "Extractor Tick", daemon = true, initialDelay = interval, period = interval) { transportManagers.forEach { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt index ea05574b30..848b3004bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt @@ -4,6 +4,11 @@ import kotlinx.serialization.Serializable @Serializable data class TransportConfiguration( - val extractorTickIntervalMS: Long = 2000, - val maxPowerRemovedPerExtractorTick: Int = 1000 -) + val extractorConfiguration: ExtractorConfiguration = ExtractorConfiguration() +) { + @Serializable + data class ExtractorConfiguration( + val extractorTickIntervalMS: Long = 2000, + val maxPowerRemovedPerExtractorTick: Int = 1000 + ) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 92ff1f3d4e..3b7063b7f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -14,7 +14,10 @@ abstract class TransportManager { abstract fun getInputProvider(): InputManager fun tick() { - powerNodeManager.network.tick() - fluidNodeManager.network.tick() + for (extractor in extractorManager.getExtractors()) { + val delta = extractor.markTicked() + powerNodeManager.network.tickExtractor(extractor.pos, delta) + fluidNodeManager.network.tickExtractor(extractor.pos, delta) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index a478c8d79d..de1fbf11af 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.manager.extractors -import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -9,26 +9,27 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import org.bukkit.persistence.PersistentDataType class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManager() { - var extractors = LongOpenHashSet() + var extractors = Long2ObjectOpenHashMap() private val mutex = Any() - override fun getExtractors(): List = synchronized(mutex) { - return extractors.toList() + override fun getExtractors(): Collection = synchronized(mutex) { + return extractors.values } override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean = synchronized(mutex) { if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != EXTRACTOR_TYPE) return false if (!manager.chunk.isInBounds(x, y, z)) return false - extractors.add(toBlockKey(x, y, z)) + val key = toBlockKey(x, y, z) + extractors[key] = ExtractorData(key) return true } - override fun removeExtractor(x: Int, y: Int, z: Int): Boolean = synchronized(mutex) { + override fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? = synchronized(mutex) { return extractors.remove(toBlockKey(x, y, z)) } - override fun removeExtractor(key: BlockKey): Boolean = synchronized(mutex) { + override fun removeExtractor(key: BlockKey): ExtractorData? = synchronized(mutex) { return extractors.remove(key) } @@ -40,10 +41,10 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag override fun onLoad() = synchronized(mutex) { val existing = pdc.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) ?: return - extractors = LongOpenHashSet(existing) + extractors = existing.associateWithTo(Long2ObjectOpenHashMap()) { ExtractorData(it) } } override fun onSave() { - pdc.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.toLongArray()) + pdc.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.keys.toLongArray()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index 60ba9eec18..d37508bd41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.manager.extractors +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -8,13 +9,13 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Material abstract class ExtractorManager { - abstract fun getExtractors(): List + abstract fun getExtractors(): Collection fun registerExtractor(key: BlockKey, ensureExtractor: Boolean): Boolean = registerExtractor(getX(key), getY(key), getZ(key), ensureExtractor) abstract fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean - abstract fun removeExtractor(key: BlockKey): Boolean - abstract fun removeExtractor(x: Int, y: Int, z: Int): Boolean + abstract fun removeExtractor(key: BlockKey): ExtractorData? + abstract fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? fun isExtractor(x: Int, y: Int, z: Int): Boolean = isExtractor(toBlockKey(x, y, z)) abstract fun isExtractor(key: BlockKey): Boolean @@ -25,4 +26,20 @@ abstract class ExtractorManager { open fun onLoad() {} open fun onSave() {} + + class ExtractorData(val pos: BlockKey) { + private var lastTicked = System.currentTimeMillis() + + private fun getDelta(time: Long): Double { + val diff = time - lastTicked + return (diff.toDouble() / IonServer.transportSettings.extractorConfiguration.extractorTickIntervalMS.toDouble()) + } + + fun markTicked(): Double { + val now = System.currentTimeMillis() + val delta = getDelta(now) + lastTicked = now + return delta + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index ac9ec49b35..30a9d7dcaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -1,16 +1,16 @@ package net.horizonsend.ion.server.features.transport.manager.extractors -import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe class ShipExtractorManager(val starship: Starship) : ExtractorManager() { - val extractors = LongOpenHashSet() + val extractors = Long2ObjectOpenHashMap() - override fun getExtractors(): List { - return extractors.toList() + override fun getExtractors(): Collection { + return extractors.values } override fun isExtractor(key: BlockKey): Boolean { @@ -19,15 +19,16 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { if (ensureExtractor && getBlockTypeSafe(starship.world, x, y, z) != EXTRACTOR_TYPE) return false - extractors.add(toBlockKey(x, y, z)) + val key = toBlockKey(x, y, z) + extractors[key] = ExtractorData(key) return true } - override fun removeExtractor(x: Int, y: Int, z: Int): Boolean { + override fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? { return extractors.remove(toBlockKey(x, y, z)) } - override fun removeExtractor(key: BlockKey): Boolean { + override fun removeExtractor(key: BlockKey): ExtractorData? { return extractors.remove(key) } @@ -36,6 +37,6 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { } fun releaseExtractors() { - + //TODO } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 6d94a14c0f..09e2d801c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -9,7 +9,7 @@ class FluidTransportCache(holder: NetworkHolder): Transport override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .build() - override fun tickExtractor(location: BlockKey) { + override fun tickExtractor(location: BlockKey, delta: Double) { } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 6b4896e20d..49965e6340 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -176,7 +176,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor } } - override fun tickExtractor(location: BlockKey) { NewTransport.executor.submit { + override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() val sources = getExtractorSourcePool(location, world).filterNot { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all @@ -187,7 +187,8 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor if (destinations.isEmpty()) return@submit - val transferred = minOf(source.powerStorage.getPower(), IonServer.transportSettings.maxPowerRemovedPerExtractorTick) + val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() + val transferred = minOf(source.powerStorage.getPower(), transferLimit) val notRemoved = source.powerStorage.removePower(transferred) val remainder = runPowerTransfer( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 24a2dd21a2..86bd4ebc52 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -17,13 +17,7 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network abstract val type: NetworkType abstract val nodeFactory: NodeCacheFactory - fun tick() { - for (extractor in holder.getExtractorManager().getExtractors()) { - tickExtractor(extractor) - } - } - - abstract fun tickExtractor(location: BlockKey) + abstract fun tickExtractor(location: BlockKey, delta: Double) fun isCached(at: BlockKey): Boolean = cache.containsKey(at) From bead8dfae6126cb1a7a6f17d3e67d3e3bdccc54f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 12:09:15 -0600 Subject: [PATCH 285/500] invalidate cache on block change --- .../horizonsend/ion/server/features/transport/NewTransport.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 66a17d758d..241640ed7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -87,6 +87,7 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } fun handleBlockEvent(world: World, x: Int, y: Int, z: Int, previousType: Material?, newType: Material) = Tasks.async { + invalidateCache(world, x, y, z) if (previousType == EXTRACTOR_TYPE && newType != EXTRACTOR_TYPE) return@async removeExtractor(world, x, y, z) if (newType == EXTRACTOR_TYPE) return@async addExtractor(world, x, y, z) } From 7335d097ae02c27f28dd266cf3f794766c746a69 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 12:15:21 -0600 Subject: [PATCH 286/500] remove power flow meter display when invalidated --- .../features/transport/nodes/cache/PowerTransportCache.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 49965e6340..a683ba2f85 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -159,6 +159,10 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun onInvalidate() { + displayHandler.remove() + } + override fun onTranslate(movement: StarshipMovement) { this.face = movement.displaceFace(this.face) displayHandler.displace(movement) From 83ac26e41c4371c83656e4030dde6d43acd8e895 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 12:23:24 -0600 Subject: [PATCH 287/500] move files around, rename stuff --- .../server/command/admin/IonChunkCommand.kt | 29 ++-- .../command/misc/TransportDebugCommand.kt | 4 +- .../modular/display/FlowMeterDisplay.kt | 4 +- .../custom/items/misc/MultimeterItem.kt | 16 +- .../multiblock/entity/MultiblockEntity.kt | 6 +- .../entity/type/power/SimplePoweredEntity.kt | 8 +- .../manager/ChunkMultiblockManager.kt | 4 +- .../multiblock/manager/MultiblockManager.kt | 4 +- .../manager/ShipMultiblockManager.kt | 4 +- .../type/fluid/ElectrolysisMultiblock.kt | 14 +- .../collector/PipedGasCollectorMultiblock.kt | 8 +- .../fluid/storage/FluidStorageMultiblock.kt | 8 +- .../manager/ChunkTransportManager.kt | 26 +-- .../transport/manager/ShipTransportManager.kt | 6 +- .../transport/manager/TransportManager.kt | 10 +- .../{NetworkHolder.kt => CacheHolder.kt} | 12 +- ...nkNetworkHolder.kt => ChunkCacheHolder.kt} | 22 +-- ...hipNetworkHolder.kt => ShipCacheHolder.kt} | 22 +-- .../transport/nodes/cache/CacheState.kt | 4 +- .../nodes/cache/FluidTransportCache.kt | 8 +- .../transport/nodes/cache/NodeCacheFactory.kt | 11 +- .../nodes/cache/PowerTransportCache.kt | 155 ++---------------- .../transport/nodes/cache/TransportCache.kt | 15 +- .../transport/nodes/inputs/InputManager.kt | 18 +- .../ComplexNode.kt} | 4 +- .../{cache/CachedNode.kt => types/Node.kt} | 16 +- .../transport/nodes/types/PowerNode.kt | 139 ++++++++++++++++ .../util/{NetworkType.kt => CacheType.kt} | 12 +- .../transport/util/NodePathfinding.kt | 18 +- 29 files changed, 312 insertions(+), 295 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/{NetworkHolder.kt => CacheHolder.kt} (79%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/{ChunkNetworkHolder.kt => ChunkCacheHolder.kt} (69%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/{ShipNetworkHolder.kt => ShipCacheHolder.kt} (63%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/{cache/ComplexCachedNode.kt => types/ComplexNode.kt} (56%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/{cache/CachedNode.kt => types/Node.kt} (69%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/{NetworkType.kt => CacheType.kt} (75%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index d085a87fdb..8fc1213c6d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -9,10 +9,11 @@ import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks -import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerInputNode -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk @@ -70,7 +71,7 @@ object IonChunkCommand : SLCommand() { @Subcommand("dump nodes") @CommandCompletion("power") /* |item|gas") */ - fun dumpNodes(sender: Player, network: NetworkType) { + fun dumpNodes(sender: Player, network: CacheType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) @@ -85,7 +86,7 @@ object IonChunkCommand : SLCommand() { @Subcommand("dump extractors") @CommandCompletion("power") /* |item|gas") */ - fun dumpExtractors(sender: Player, network: NetworkType) { + fun dumpExtractors(sender: Player, network: CacheType) { val ionChunk = sender.chunk.ion() val extractors = network.get(ionChunk).holder.getExtractorManager() @@ -98,7 +99,7 @@ object IonChunkCommand : SLCommand() { @Subcommand("dump") @CommandCompletion("power") - fun dumpNetwork(sender: Player, network: NetworkType) { + fun dumpNetwork(sender: Player, network: CacheType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) @@ -123,7 +124,7 @@ object IonChunkCommand : SLCommand() { } @Subcommand("get node key") - fun getNode(sender: Player, key: Long, network: NetworkType) { + fun getNode(sender: Player, key: Long, network: CacheType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) @@ -131,30 +132,30 @@ object IonChunkCommand : SLCommand() { } @Subcommand("get node look") - fun getNode(sender: Player, network: NetworkType) { + fun getNode(sender: Player, network: CacheType) { val (node, location) = requireLookingAt(sender, network) sender.information("Targeted node: $node at ${toVec3i(location)}") } @Subcommand("test extractor") fun onTick(sender: Player) { - val (node, location) = requireLookingAt(sender, NetworkType.POWER) - if (node !is PowerTransportCache.PowerNode.PowerExtractorNode) fail { "Extractor not targeted" } + val (node, location) = requireLookingAt(sender, CacheType.POWER) + if (node !is PowerNode.PowerExtractorNode) fail { "Extractor not targeted" } val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } - val grid = NetworkType.POWER.get(chunk) as PowerTransportCache + val grid = CacheType.POWER.get(chunk) as PowerTransportCache grid.tickExtractor(location, 1.0) } @Subcommand("test flood") - fun onTestFloodFill(sender: Player, network: NetworkType) { + fun onTestFloodFill(sender: Player, network: CacheType) { sender.information("Trying to find input nodes") val (cached, location) = requireLookingAt(sender, network) - val destinations = getNetworkDestinations(NetworkType.POWER, sender.world, location) { true } + val destinations = getNetworkDestinations(CacheType.POWER, sender.world, location) { true } sender.information("${destinations.size} destinations") sender.highlightBlocks(destinations.map(::toVec3i), 50L) } - private fun requireLookingAt(sender: Player, network: NetworkType): Pair { + private fun requireLookingAt(sender: Player, network: CacheType): Pair { val targeted = sender.getTargetBlock(null, 10) val ionChunk = targeted.chunk.ion() val grid = network.get(ionChunk) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 9ec5e507f8..ed62ca77e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.old.Wires -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -43,7 +43,7 @@ object TransportDebugCommand : SLCommand() { } @Subcommand("dump inputs") - fun dumpInputs(sender: Player, type: NetworkType) { + fun dumpInputs(sender: Player, type: CacheType) { val inputManager = sender.world.ion.inputManager val loc = Vec3i(sender.location) val inputs = inputManager.getLocations(type) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index 43e3c39fbc..69b7fcffec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.client.display.modular.display import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text @@ -10,7 +10,7 @@ import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW class FlowMeterDisplay( - private val meter: PowerTransportCache.PowerNode.PowerFlowMeter, + private val meter: PowerNode.PowerFlowMeter, offsetLeft: Double, offsetUp: Double, offsetBack: Double, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 55da6e3cfa..048851b38a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -7,8 +7,8 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.PathfindingNodeWrapper import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getHeuristic @@ -87,23 +87,23 @@ object MultimeterItem : CustomItem("Multimeter") { val secondPoint = itemStack.itemMeta.persistentDataContainer.get(Z, LONG) ?: return val networkTypeIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) - val networkType = NetworkType.entries[networkTypeIndex] + val cacheType = CacheType.entries[networkTypeIndex] - val firstNode = networkType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") + val firstNode = cacheType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") - val path = getIdealPath(audience, CachedNode.NodePositionData(firstNode, world, firstPoint, BlockFace.SELF), secondPoint) + val path = getIdealPath(audience, Node.NodePositionData(firstNode, world, firstPoint, BlockFace.SELF), secondPoint) val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${toVec3i(secondPoint)} at ${toVec3i(secondPoint)} is $resistance") } private fun cycleNetworks(audience: Audience, world: World, itemStack: ItemStack) { val currentIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) - val newIndex = (currentIndex + 1) % NetworkType.entries.size + val newIndex = (currentIndex + 1) % CacheType.entries.size itemStack.updateMeta { it.persistentDataContainer.set(NODE_VARIANT, INTEGER, newIndex) } - audience.success("Set network type to ${NetworkType.entries[newIndex]}") + audience.success("Set network type to ${CacheType.entries[newIndex]}") tryCheckResistance(audience, world, itemStack) } @@ -111,7 +111,7 @@ object MultimeterItem : CustomItem("Multimeter") { /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ - private fun getIdealPath(audience: Audience, fromNode: CachedNode.NodePositionData, toPos: BlockKey): Array? { + private fun getIdealPath(audience: Audience, fromNode: Node.NodePositionData, toPos: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index bb8477022c..43d2d34235 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -284,14 +284,14 @@ abstract class MultiblockEntity( manager.markChanged() } - fun registerInputs(type: NetworkType, locations: Set) { + fun registerInputs(type: CacheType, locations: Set) { val inputManager = manager.getInputManager() for (location in locations) { inputManager.registerInput(type, toBlockKey(location), this) } } - fun releaseInputs(type: NetworkType, locations: Set) { + fun releaseInputs(type: CacheType, locations: Set) { val inputManager = manager.getInputManager() for (location in locations) { inputManager.deRegisterInput(type, toBlockKey(location), this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index bb41fe5e57..dc334f9800 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World @@ -46,14 +46,14 @@ abstract class SimplePoweredEntity( ).register() override fun onLoad() { - registerInputs(NetworkType.POWER, getPowerInputLocations()) + registerInputs(CacheType.POWER, getPowerInputLocations()) } override fun handleRemoval() { - releaseInputs(NetworkType.POWER, getPowerInputLocations()) + releaseInputs(CacheType.POWER, getPowerInputLocations()) } override fun onUnload() { - releaseInputs(NetworkType.POWER, getPowerInputLocations()) + releaseInputs(CacheType.POWER, getPowerInputLocations()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 87f9dd89ff..600713b19c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultibl import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD @@ -42,7 +42,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag chunk.inner.minecraft.isUnsaved = true } - override fun getNetwork(type: NetworkType): TransportCache { + override fun getNetwork(type: CacheType): TransportCache { return type.get(chunk) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 75e1f8826e..bf59ca423b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -9,7 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing @@ -37,7 +37,7 @@ abstract class MultiblockManager(val log: Logger) { fun getAllMultiblockEntities() = multiblockEntities - abstract fun getNetwork(type: NetworkType): TransportCache + abstract fun getNetwork(type: CacheType): TransportCache abstract fun getSignUnsavedTime(): Long diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index a0bfedf317..03f805fea5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -14,7 +14,7 @@ import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -45,7 +45,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override fun getSignUnsavedTime(): Long = 0 override fun markChanged() {} - override fun getNetwork(type: NetworkType): TransportCache { + override fun getNetwork(type: CacheType): TransportCache { return type.get(starship) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index a1cebd5da0..b98c737bde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -29,7 +29,7 @@ import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.sta import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 @@ -244,18 +244,18 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf(Vec3i(0, -1, 0)) override fun onLoad() { - registerInputs(NetworkType.FLUID, getFluidInputLocations()) + registerInputs(CacheType.FLUID, getFluidInputLocations()) } override fun onUnload() { - releaseInputs(NetworkType.FLUID, getFluidInputLocations()) + releaseInputs(CacheType.FLUID, getFluidInputLocations()) } override fun handleRemoval() { - releaseInputs(NetworkType.FLUID, getFluidInputLocations()) + releaseInputs(CacheType.FLUID, getFluidInputLocations()) } override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 86e3a290fb..5e9898174c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.manager.holders.ChunkNetworkHolder +import net.horizonsend.ion.server.features.transport.manager.holders.ChunkCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager @@ -15,8 +15,8 @@ import org.bukkit.block.data.BlockData class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { override val extractorManager: ExtractorManager = ChunkExtractorManager(this) - override val powerNodeManager = ChunkNetworkHolder(this) { PowerTransportCache(it) } - override val fluidNodeManager = ChunkNetworkHolder(this) { FluidTransportCache(it) } + override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } + override val fluidNodeManager = ChunkCacheHolder(this) { FluidTransportCache(it) } // val pipeGrid = PowerNodeManager(this) // TODO override fun getInputProvider(): InputManager { @@ -40,31 +40,31 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { } fun invalidateCache(key: BlockKey) { - powerNodeManager.network.invalidate(key) - fluidNodeManager.network.invalidate(key) + powerNodeManager.cache.invalidate(key) + fluidNodeManager.cache.invalidate(key) } fun processBlockRemoval(key: BlockKey) { - powerNodeManager.network.invalidate(key) - fluidNodeManager.network.invalidate(key) + powerNodeManager.cache.invalidate(key) + fluidNodeManager.cache.invalidate(key) // pipeGrid.processBlockRemoval(key) } fun processBlockChange(block: Block) { - powerNodeManager.network.invalidate(toBlockKey(block.x, block.y, block.z)) - fluidNodeManager.network.invalidate(toBlockKey(block.x, block.y, block.z)) + powerNodeManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) + fluidNodeManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) // pipeGrid.processBlockAddition(key, new) } fun processBlockChange(position: BlockKey, data: BlockData) { - powerNodeManager.network.invalidate(position) - fluidNodeManager.network.invalidate(position) + powerNodeManager.cache.invalidate(position) + fluidNodeManager.cache.invalidate(position) // pipeGrid.processBlockAddition(key, new) } fun refreshBlock(position: BlockKey) { - powerNodeManager.network.invalidate(position) - fluidNodeManager.network.invalidate(position) + powerNodeManager.cache.invalidate(position) + fluidNodeManager.cache.invalidate(position) // pipeGrid.processBlockAddition(key, new) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 6327aae0c4..191f96939d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager -import net.horizonsend.ion.server.features.transport.manager.holders.ShipNetworkHolder +import net.horizonsend.ion.server.features.transport.manager.holders.ShipCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager @@ -14,8 +14,8 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { override val extractorManager: ShipExtractorManager = ShipExtractorManager(starship) private val inputManager = ShipInputManager(this) - override val powerNodeManager = ShipNetworkHolder(this) { PowerTransportCache(it) } - override val fluidNodeManager = ShipNetworkHolder(this) { FluidTransportCache(it) } + override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } + override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } init { load() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 3b7063b7f0..82d7d4231e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -1,23 +1,23 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager abstract class TransportManager { abstract val extractorManager: ExtractorManager - abstract val powerNodeManager: NetworkHolder - abstract val fluidNodeManager: NetworkHolder + abstract val powerNodeManager: CacheHolder + abstract val fluidNodeManager: CacheHolder abstract fun getInputProvider(): InputManager fun tick() { for (extractor in extractorManager.getExtractors()) { val delta = extractor.markTicked() - powerNodeManager.network.tickExtractor(extractor.pos, delta) - fluidNodeManager.network.tickExtractor(extractor.pos, delta) + powerNodeManager.cache.tickExtractor(extractor.pos, delta) + fluidNodeManager.cache.tickExtractor(extractor.pos, delta) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt similarity index 79% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt index 7f77e51e2c..17d5079234 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/NetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt @@ -1,14 +1,14 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode -import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World -interface NetworkHolder { - val network: T +interface CacheHolder { + val cache: T fun getWorld(): World @@ -27,12 +27,12 @@ interface NetworkHolder { /** * Get a node inside this network **/ - fun getInternalNode(key: BlockKey): CachedNode? + fun getInternalNode(key: BlockKey): Node? /** * Method used to access nodes inside, and outside the network **/ - fun getOrCacheGlobalNode(key: BlockKey): CachedNode? + fun getOrCacheGlobalNode(key: BlockKey): Node? fun getMultiblockManager(): MultiblockManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt index f0184fc749..65acbfe3db 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode -import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -12,23 +12,23 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import org.bukkit.World import kotlin.properties.Delegates -class ChunkNetworkHolder private constructor (val manager: ChunkTransportManager) : NetworkHolder { - override var network: T by Delegates.notNull(); private set +class ChunkCacheHolder private constructor (val manager: ChunkTransportManager) : CacheHolder { + override var cache: T by Delegates.notNull(); private set - constructor(manager: ChunkTransportManager, network: (ChunkNetworkHolder) -> T) : this(manager) { - this.network = network(this) + constructor(manager: ChunkTransportManager, network: (ChunkCacheHolder) -> T) : this(manager) { + this.cache = network(this) } override fun getWorld(): World = manager.chunk.world - override fun getOrCacheGlobalNode(key: BlockKey): CachedNode? { + override fun getOrCacheGlobalNode(key: BlockKey): Node? { val chunkX = getX(key).shr(4) val chunkZ = getZ(key).shr(4) val isThisChunk = chunkX == manager.chunk.x && chunkZ == manager.chunk.z if (isThisChunk) { - return network.getOrCache(key) + return cache.getOrCache(key) } val xDiff = manager.chunk.x - chunkX @@ -38,11 +38,11 @@ class ChunkNetworkHolder private constructor (val manager: Ch if (zDiff > 1 || zDiff < -1) return null val chunk = IonChunk[getWorld(), chunkX, chunkZ] ?: return null - return network.type.get(chunk).getOrCache(key) + return cache.type.get(chunk).getOrCache(key) } - override fun getInternalNode(key: BlockKey): CachedNode? { - return network.getOrCache(key) + override fun getInternalNode(key: BlockKey): Node? { + return cache.getOrCache(key) } override fun getMultiblockManager(): MultiblockManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt similarity index 63% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 5893f762cf..9bd592deae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipNetworkHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -1,37 +1,37 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode -import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World import kotlin.properties.Delegates -class ShipNetworkHolder(val manager: ShipTransportManager) : NetworkHolder { - override var network: T by Delegates.notNull(); private set +class ShipCacheHolder(val manager: ShipTransportManager) : CacheHolder { + override var cache: T by Delegates.notNull(); private set - constructor(manager: ShipTransportManager, network: (ShipNetworkHolder) -> T) : this(manager) { - this.network = network(this) + constructor(manager: ShipTransportManager, network: (ShipCacheHolder) -> T) : this(manager) { + this.cache = network(this) } override fun getWorld(): World = manager.starship.world override fun handleLoad() { manager.starship.iterateBlocks { x, y, z -> - IonChunk[manager.starship.world, x, z]?.let { network.type.get(it).invalidate(x, y, z) } - network.cache(toBlockKey(x, y, z)) + IonChunk[manager.starship.world, x, z]?.let { cache.type.get(it).invalidate(x, y, z) } + cache.cache(toBlockKey(x, y, z)) } } - override fun getInternalNode(key: BlockKey): CachedNode? { - return network.getCached(key) + override fun getInternalNode(key: BlockKey): Node? { + return cache.getCached(key) } - override fun getOrCacheGlobalNode(key: BlockKey): CachedNode? { + override fun getOrCacheGlobalNode(key: BlockKey): Node? { // Ship networks cannot access the outside world return getInternalNode(key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt index 41735351aa..6b2365e846 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CacheState.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.features.transport.nodes.types.Node + sealed interface CacheState { data object Empty: CacheState - data class Present(val node: CachedNode): CacheState + data class Present(val node: Node): CacheState } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 09e2d801c7..5fe7946a71 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -class FluidTransportCache(holder: NetworkHolder): TransportCache(holder) { - override val type: NetworkType = NetworkType.FLUID +class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { + override val type: CacheType = CacheType.FLUID override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .build() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index f02b4017a3..f9d1c94b24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe @@ -10,7 +11,7 @@ import org.bukkit.block.data.BlockData import kotlin.reflect.KClass class NodeCacheFactory private constructor(private val materialHandlers: Map>) { - fun cache(block: Block): CachedNode? { + fun cache(block: Block): Node? { val type = block.getTypeSafe() ?: return null val materialFactory = materialHandlers[type] ?: return null val blockData = getBlockDataSafe(block.world, block.x, block.y, block.z) ?: return null @@ -22,12 +23,12 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map>() - inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> CachedNode): Builder { + inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node): Builder { this.materialHandlers[material] = MaterialHandler(T::class, constructor) return this } - fun addSimpleNode(material: Material, node: CachedNode): Builder { + fun addSimpleNode(material: Material, node: Node): Builder { this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } return this } @@ -37,8 +38,8 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val blockDataClass: KClass, val constructor: (T, BlockKey) -> CachedNode) { - fun construct(blockData: BlockData, key: BlockKey): CachedNode { + class MaterialHandler(val blockDataClass: KClass, val constructor: (T, BlockKey) -> Node) { + fun construct(blockData: BlockData, key: BlockKey): Node { @Suppress("UNCHECKED_CAST") return constructor.invoke(blockData as T, key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index a683ba2f85..94ae5ea7da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,20 +1,17 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth -import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerFlowMeter -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache.PowerNode.PowerInputNode -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations @@ -26,14 +23,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.faces import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor.GREEN -import org.bukkit.Axis import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD import org.bukkit.Material.IRON_BLOCK @@ -49,8 +40,8 @@ import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod import kotlin.math.roundToInt -class PowerTransportCache(holder: NetworkHolder) : TransportCache(holder) { - override val type: NetworkType = NetworkType.POWER +class PowerTransportCache(holder: CacheHolder) : TransportCache(holder) { + override val type: CacheType = CacheType.POWER override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) .addSimpleNode(SPONGE, PowerNode.SpongeNode) @@ -62,130 +53,12 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() - sealed interface PowerNode : CachedNode { - override val networkType: NetworkType get() = NetworkType.POWER - - data object SpongeNode : PowerNode { - override val pathfindingResistance: Double = 1.0 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - } - - data class EndRodNode(var axis: Axis) : PowerNode, ComplexCachedNode { - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = offset.axis == this.axis - override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) - override fun onTranslate(movement: StarshipMovement) { - this.axis = movement.displaceFace(this.axis.faces.first).axis - } - } - - data object PowerExtractorNode : PowerNode { - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = false - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is PowerInputNode - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - } - - data object PowerMergeNode : PowerNode { - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is SpongeNode - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is SpongeNode - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - } - - data object PowerInvertedMergeNode : PowerNode { - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = other is EndRodNode - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = other !is EndRodNode - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - } - - data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexCachedNode { - val displayHandler = DisplayHandlers.newBlockOverlay( - cache.holder.getWorld(), - toVec3i(location), - face, - FlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) - ).register() - - private val STORED_AVERAGES = 20 - private val averages = mutableListOf() - - fun onCompleteChain(transferred: Int) { - addTransferred(TransferredPower(transferred, System.currentTimeMillis())) - displayHandler.update() - } - - private fun addTransferred(transferredSnapshot: TransferredPower) { - val currentSize = averages.size - - if (currentSize < STORED_AVERAGES) { - averages.add(transferredSnapshot) - return - } - - // If it is full, shift all averages to the right - for (index in 18 downTo 0) { - averages[index + 1] = averages[index] - } - - averages[0] = transferredSnapshot - } - - private fun calculateAverage(): Double { - val sum = averages.sumOf { it.transferred } - - val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 - - return sum / timeDiff - } - - fun formatFlow(): Component { - var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) - - // If no averages, or no power has been moved in 5 seconds, go to 0 - if (averages.isEmpty() || System.currentTimeMillis() - averages.maxOf { it.time } > 5000) { - avg = 0.0 - } - - return ofChildren(FlowMeterDisplay.firstLine, text(avg, GREEN), FlowMeterDisplay.secondLine) - } - - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = true - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - - override fun onInvalidate() { - displayHandler.remove() - } - - override fun onTranslate(movement: StarshipMovement) { - this.face = movement.displaceFace(this.face) - displayHandler.displace(movement) - } - - private data class TransferredPower(val transferred: Int, val time: Long) - } - - data object PowerInputNode : PowerNode { - override val pathfindingResistance: Double = 0.0 - override fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean = true - override fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean = false - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(NetworkType.POWER, location).filterIsInstance() - } - } - override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() val sources = getExtractorSourcePool(location, world).filterNot { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all - val destinations: LongOpenHashSet = getNetworkDestinations(NetworkType.POWER, world, location) { + val destinations: LongOpenHashSet = getNetworkDestinations(CacheType.POWER, world, location) { world.ion.inputManager.getHolders(type, it.position).isNotEmpty() } @@ -196,7 +69,7 @@ class PowerTransportCache(holder: NetworkHolder) : Transpor val notRemoved = source.powerStorage.removePower(transferred) val remainder = runPowerTransfer( - CachedNode.NodePositionData( + Node.NodePositionData( PowerNode.PowerExtractorNode, world, location, @@ -228,7 +101,7 @@ fun getExtractorSourcePool(extractorLocation: BlockKey, world: World): List { val inputManager = world.ion.inputManager - val registered = inputManager.getHolders(NetworkType.POWER, location) + val registered = inputManager.getHolders(CacheType.POWER, location) val adjacentBlocks = ADJACENT_BLOCK_FACES.mapNotNull { val block = getBlockIfLoaded(world, getX(location), getY(location), getZ(location)) ?: return@mapNotNull null val adjacent = block.getRelativeIfLoaded(it)?.state as? Sign ?: return@mapNotNull null @@ -271,12 +144,12 @@ fun distributePower(destinations: List, power: Int): In /** * Runs the power transfer from the source to the destinations. pending rewrite **/ -private fun runPowerTransfer(source: CachedNode.NodePositionData, destinations: List, availableTransferPower: Int): Int { +private fun runPowerTransfer(source: Node.NodePositionData, destinations: List, availableTransferPower: Int): Int { if (destinations.isEmpty()) return availableTransferPower val numDestinations = destinations.size - val paths: Array?> = Array(numDestinations) { runCatching { + val paths: Array?> = Array(numDestinations) { runCatching { getIdealPath(source, destinations[it]) }.getOrNull() } @@ -340,7 +213,7 @@ private fun getRemainingCapacity(destinations: List): I return destinations.sumOf { it.powerStorage.getRemainingCapacity() } } -private fun completeChain(path: Array?, transferred: Int) { +private fun completeChain(path: Array?, transferred: Int) { path?.forEach { if (it.type is PowerFlowMeter) it.type.onCompleteChain(transferred) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 86bd4ebc52..bc27e5ff9d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,8 +1,9 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap -import net.horizonsend.ion.server.features.transport.manager.holders.NetworkHolder -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -11,17 +12,17 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block -abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network holder, works for now */) { +abstract class TransportCache(val holder: CacheHolder<*> /* TODO temp network holder, works for now */) { private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() - abstract val type: NetworkType + abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory abstract fun tickExtractor(location: BlockKey, delta: Double) fun isCached(at: BlockKey): Boolean = cache.containsKey(at) - fun getCached(at: BlockKey): CachedNode? { + fun getCached(at: BlockKey): Node? { val state = cache[at] ?: return null return when (state) { is CacheState.Empty -> null @@ -29,7 +30,7 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network } } - fun getOrCache(location: BlockKey): CachedNode? { + fun getOrCache(location: BlockKey): Node? { if (isCached(location)) return getCached(location) else return cache(location, getBlockIfLoaded(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return null) } @@ -40,7 +41,7 @@ abstract class TransportCache(val holder: NetworkHolder<*> /* TODO temp network cache(location, block) } - fun cache(location: BlockKey, block: Block): CachedNode? { + fun cache(location: BlockKey, block: Block): Node? { val type = nodeFactory.cache(block) val state = if (type == null) CacheState.Empty else CacheState.Present(type) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt index 4cf03c710d..f170ff3869 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt @@ -3,35 +3,35 @@ package net.horizonsend.ion.server.features.transport.nodes.inputs import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import java.util.concurrent.ConcurrentHashMap abstract class InputManager { - private val typeManagers = ConcurrentHashMap() + private val typeManagers = ConcurrentHashMap() - private fun getTypeManager(type: NetworkType): TypeManager { + private fun getTypeManager(type: CacheType): TypeManager { return typeManagers.getOrPut(type) { TypeManager(this, type) } } - fun registerInput(type: NetworkType, location: BlockKey, holder: MultiblockEntity) { + fun registerInput(type: CacheType, location: BlockKey, holder: MultiblockEntity) { getTypeManager(type).add(location, holder) } - fun deRegisterInput(type: NetworkType, location: BlockKey, holder: MultiblockEntity) { + fun deRegisterInput(type: CacheType, location: BlockKey, holder: MultiblockEntity) { getTypeManager(type).remove(location, holder) } - fun getHolders(type: NetworkType, location: BlockKey): Set { + fun getHolders(type: CacheType, location: BlockKey): Set { return getTypeManager(type).getAllHolders(location) } - fun getInputData(type: NetworkType, location: BlockKey): TypeManager.InputData? = + fun getInputData(type: CacheType, location: BlockKey): TypeManager.InputData? = getTypeManager(type).getRaw(location) - fun getLocations(type: NetworkType) = getTypeManager(type).getAllLocations() + fun getLocations(type: CacheType) = getTypeManager(type).getAllLocations() - class TypeManager(val manager: InputManager, val type: NetworkType) { + class TypeManager(val manager: InputManager, val type: CacheType) { private val inputLocations = Long2ObjectOpenHashMap() fun getAllLocations() = inputLocations.keys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt similarity index 56% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt index ec2ea916ff..d3964749ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ComplexCachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.transport.nodes.cache +package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -interface ComplexCachedNode { +interface ComplexNode { fun onTranslate(movement: StarshipMovement) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt index fea29d208f..5de8c49c24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/CachedNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt @@ -1,14 +1,14 @@ -package net.horizonsend.ion.server.features.transport.nodes.cache +package net.horizonsend.ion.server.features.transport.nodes.types -import net.horizonsend.ion.server.features.transport.util.NetworkType +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.World import org.bukkit.block.BlockFace -interface CachedNode { - val networkType: NetworkType +interface Node { + val cacheType: CacheType val pathfindingResistance: Double fun getTransferableDirections(backwards: BlockFace): Set @@ -16,12 +16,12 @@ interface CachedNode { /** * Adds any restrictions on transferring to another node **/ - fun canTransferTo(other: CachedNode, offset: BlockFace): Boolean + fun canTransferTo(other: Node, offset: BlockFace): Boolean /** * Adds any restrictions on transferring from another node **/ - fun canTransferFrom(other: CachedNode, offset: BlockFace): Boolean + fun canTransferFrom(other: Node, offset: BlockFace): Boolean fun getNextNodes(world: World, position: BlockKey, backwards: BlockFace): List { val adjacent = getTransferableDirections(backwards) @@ -29,7 +29,7 @@ interface CachedNode { for (adjacentFace in adjacent) { val pos = getRelative(position, adjacentFace) - val cached = getOrCacheNode(networkType, world, pos) ?: continue + val cached = getOrCacheNode(cacheType, world, pos) ?: continue if (!cached.canTransferFrom(this, adjacentFace) || !canTransferTo(cached, adjacentFace)) continue @@ -39,7 +39,7 @@ interface CachedNode { return nodes } - data class NodePositionData(val type: CachedNode, val world: World, val position: BlockKey, val offset: BlockFace) { + data class NodePositionData(val type: Node, val world: World, val position: BlockKey, val offset: BlockFace) { fun getNextNodes(): List = type.getNextNodes(world, position, offset.oppositeFace) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt new file mode 100644 index 0000000000..555c135585 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -0,0 +1,139 @@ +package net.horizonsend.ion.server.features.transport.nodes.types + +import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.faces +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.Axis +import org.bukkit.World +import org.bukkit.block.BlockFace + +sealed interface PowerNode : Node { + override val cacheType: CacheType get() = CacheType.POWER + + data object SpongeNode : PowerNode { + override val pathfindingResistance: Double = 1.0 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data class EndRodNode(var axis: Axis) : PowerNode, ComplexNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis + override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) + override fun onTranslate(movement: StarshipMovement) { + this.axis = movement.displaceFace(this.axis.faces.first).axis + } + } + + data object PowerExtractorNode : PowerNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is PowerInputNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data object PowerMergeNode : PowerNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is SpongeNode + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is SpongeNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data object PowerInvertedMergeNode : PowerNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is EndRodNode + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is EndRodNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexNode { + val displayHandler = DisplayHandlers.newBlockOverlay( + cache.holder.getWorld(), + toVec3i(location), + face, + FlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) + ).register() + + private val STORED_AVERAGES = 20 + private val averages = mutableListOf() + + fun onCompleteChain(transferred: Int) { + addTransferred(TransferredPower(transferred, System.currentTimeMillis())) + displayHandler.update() + } + + private fun addTransferred(transferredSnapshot: TransferredPower) { + val currentSize = averages.size + + if (currentSize < STORED_AVERAGES) { + averages.add(transferredSnapshot) + return + } + + // If it is full, shift all averages to the right + for (index in 18 downTo 0) { + averages[index + 1] = averages[index] + } + + averages[0] = transferredSnapshot + } + + private fun calculateAverage(): Double { + val sum = averages.sumOf { it.transferred } + + val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 + + return sum / timeDiff + } + + fun formatFlow(): Component { + var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) + + // If no averages, or no power has been moved in 5 seconds, go to 0 + if (averages.isEmpty() || System.currentTimeMillis() - averages.maxOf { it.time } > 5000) { + avg = 0.0 + } + + return ofChildren(FlowMeterDisplay.firstLine, Component.text(avg, NamedTextColor.GREEN), FlowMeterDisplay.secondLine) + } + + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override fun onInvalidate() { + displayHandler.remove() + } + + override fun onTranslate(movement: StarshipMovement) { + this.face = movement.displaceFace(this.face) + displayHandler.displace(movement) + } + + private data class TransferredPower(val transferred: Int, val time: Long) + } + + data object PowerInputNode : PowerNode { + override val pathfindingResistance: Double = 0.0 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.POWER, location).filterIsInstance() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt similarity index 75% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index f8a8f8da80..b00a385a15 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NetworkType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -8,23 +8,23 @@ import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.NamespacedKey -enum class NetworkType(val namespacedKey: NamespacedKey) { +enum class CacheType(val namespacedKey: NamespacedKey) { POWER(NamespacedKeys.POWER_TRANSPORT) { override fun get(chunk: IonChunk): PowerTransportCache { - return chunk.transportNetwork.powerNodeManager.network + return chunk.transportNetwork.powerNodeManager.cache } override fun get(ship: ActiveStarship): PowerTransportCache { - return ship.transportManager.powerNodeManager.network + return ship.transportManager.powerNodeManager.cache } }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { override fun get(chunk: IonChunk): FluidTransportCache { - return chunk.transportNetwork.fluidNodeManager.network + return chunk.transportNetwork.fluidNodeManager.cache } override fun get(ship: ActiveStarship): FluidTransportCache { - return ship.transportManager.fluidNodeManager.network + return ship.transportManager.fluidNodeManager.cache } }, @@ -36,6 +36,6 @@ enum class NetworkType(val namespacedKey: NamespacedKey) { companion object { private val byKey = entries.associateBy { it.namespacedKey } - operator fun get(key: NamespacedKey): NetworkType = byKey[key]!! + operator fun get(key: NamespacedKey): CacheType = byKey[key]!! } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 6b3b2e653a..275dd3e1f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.server.features.transport.nodes.cache.CachedNode +import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -15,15 +15,15 @@ import org.bukkit.block.BlockFace import java.util.PriorityQueue import kotlin.math.roundToInt -fun getOrCacheNode(type: NetworkType, world: World, pos: BlockKey): CachedNode? { +fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { val chunk = IonChunk[world, getX(pos).shr(4), getZ(pos).shr(4)] ?: return null return type.get(chunk).getOrCache(pos) } -inline fun getNetworkDestinations(networkType: NetworkType, world: World, originPos: BlockKey, check: (CachedNode.NodePositionData) -> Boolean): LongOpenHashSet { - val originNode = getOrCacheNode(networkType, world, originPos) ?: return LongOpenHashSet() +inline fun getNetworkDestinations(cacheType: CacheType, world: World, originPos: BlockKey, check: (Node.NodePositionData) -> Boolean): LongOpenHashSet { + val originNode = getOrCacheNode(cacheType, world, originPos) ?: return LongOpenHashSet() - val visitQueue = ArrayDeque() + val visitQueue = ArrayDeque() val visitedSet = LongOpenHashSet() val destinations = LongOpenHashSet() @@ -52,7 +52,7 @@ inline fun getNetworkDestinations(networkType: NetworkTy /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ -fun getIdealPath(from: CachedNode.NodePositionData, to: BlockKey): Array? { +fun getIdealPath(from: Node.NodePositionData, to: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -137,13 +137,13 @@ fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: BlockKey): Int { * @param parent The parent node **/ data class PathfindingNodeWrapper( - val node: CachedNode.NodePositionData, + val node: Node.NodePositionData, var parent: PathfindingNodeWrapper?, var g: Int, var f: Int ) { // Compiles the path - fun buildPath(): Array { + fun buildPath(): Array { val list = mutableListOf(this.node) var current: PathfindingNodeWrapper? = this @@ -182,6 +182,6 @@ data class PathfindingNodeWrapper( // } -fun calculatePathResistance(path: Array?): Double? { +fun calculatePathResistance(path: Array?): Double? { return path?.sumOf { it.type.pathfindingResistance } } From 3853d21758f1d1b9d6f514630b0907ec05758b2d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 13:34:31 -0600 Subject: [PATCH 288/500] clean up power transfer code --- .../custom/items/misc/MultimeterItem.kt | 2 +- .../features/multiblock/MultiblockEntities.kt | 20 +- .../nodes/cache/PowerTransportCache.kt | 200 ++++++++++-------- .../transport/util/NodePathfinding.kt | 28 +-- 4 files changed, 138 insertions(+), 112 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 048851b38a..48fcd93fc0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -149,7 +149,7 @@ object MultimeterItem : CustomItem("Multimeter") { queueRemove(current) visited.add(current.node.position) - val neighbors = getNeighbors(current, audience) + val neighbors = getNeighbors(current) if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index ac63f79dd9..8d6200ebe9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.multiblock +import org.bukkit.block.Sign as SignState +import org.bukkit.block.data.type.WallSign as SignData import com.destroystokyo.paper.event.server.ServerTickEndEvent import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -11,13 +13,13 @@ import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.World import org.bukkit.block.Block -import org.bukkit.block.Sign import org.bukkit.event.EventHandler /** @@ -49,11 +51,21 @@ object MultiblockEntities : SLEventListener() { return getMultiblockEntity(origin.world, origin.x, origin.y, origin.z) } - fun getMultiblockEntity(sign: Sign): MultiblockEntity? { + fun getMultiblockEntity(sign: SignState): MultiblockEntity? { val origin = MultiblockEntity.getOriginFromSign(sign) return getMultiblockEntity(sign.world, origin.x, origin.y, origin.z) } + fun getMultiblockEntity(signLocation: BlockKey, world: World, sign: SignData): MultiblockEntity? { + val origin = getRelative(signLocation, sign.facing.oppositeFace) + return getMultiblockEntity(world, getX(origin), getY(origin), getZ(origin)) + } + + fun getMultiblockEntity(signX: Int, signY: Int, signZ: Int, world: World, sign: SignData): MultiblockEntity? { + val structureDirection = sign.facing.oppositeFace + return getMultiblockEntity(world, signX + structureDirection.modX, signY + structureDirection.modY, signZ + structureDirection.modZ) + } + /** * Add a new multiblock entity to the chunk **/ @@ -88,7 +100,7 @@ object MultiblockEntities : SLEventListener() { return multiblock.createEntity(manager, stored, manager.world, stored.x, stored.y, stored.z, stored.signOffset) } - fun loadFromSign(sign: Sign) { + fun loadFromSign(sign: SignState) { val multiblockType = MultiblockAccess.getFast(sign) as? EntityMultiblock<*> ?: return val data = sign.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return migrateFromSign(sign, multiblockType) @@ -109,7 +121,7 @@ object MultiblockEntities : SLEventListener() { } } - fun migrateFromSign(sign: Sign, type: EntityMultiblock<*>) { + fun migrateFromSign(sign: SignState, type: EntityMultiblock<*>) { val origin = MultiblockEntity.getOriginFromSign(sign) val ionChunk = getIonChunk(sign.world, origin.x, origin.z) ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 94ae5ea7da..7fba13f1bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity @@ -35,8 +34,8 @@ import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Sign import org.bukkit.block.data.type.Observer +import org.bukkit.block.data.type.WallSign import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod import kotlin.math.roundToInt @@ -55,18 +54,21 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() - val sources = getExtractorSourcePool(location, world).filterNot { it.powerStorage.isEmpty() } + val sources = getPowerExtractorSourcePool(location, world) val source = sources.randomOrNull() ?: return@submit //TODO take from all - val destinations: LongOpenHashSet = getNetworkDestinations(CacheType.POWER, world, location) { - world.ion.inputManager.getHolders(type, it.position).isNotEmpty() + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(CacheType.POWER, world, location) { node -> + world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } } if (destinations.isEmpty()) return@submit val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() val transferred = minOf(source.powerStorage.getPower(), transferLimit) - val notRemoved = source.powerStorage.removePower(transferred) + + // Store this just in case + val missing = source.powerStorage.removePower(transferred) val remainder = runPowerTransfer( Node.NodePositionData( @@ -75,42 +77,128 @@ class PowerTransportCache(holder: CacheHolder) : TransportC location, BlockFace.SELF ), - destinations.toMutableList(), - (transferred - notRemoved) + destinations, + (transferred - missing) ) -// if (transferred == remainder) { -// TODO skip growing number of ticks if nothing to do -// } - if (remainder > 0) { source.powerStorage.addPower(remainder) } }} -} -// These methods are outside the class for speed -fun getExtractorSourcePool(extractorLocation: BlockKey, world: World): List { - return ADJACENT_BLOCK_FACES.flatMap { - getPoweredEntities(world, getRelative(extractorLocation, it)) - }.filterIsInstance() + fun getPowerExtractorSourcePool(extractorLocation: BlockKey, world: World): List { + val sources = mutableListOf() + + for (face in ADJACENT_BLOCK_FACES) { + val inputLocation = getRelative(extractorLocation, face) + if (holder.getOrCacheGlobalNode(inputLocation) !is PowerInputNode) continue + val entities = getInputEntities(world, inputLocation) + + for (entity in entities) { + if (entity !is PoweredMultiblockEntity) continue + if (entity.powerStorage.isFull()) continue + sources.add(entity) + } + } + + return sources + } + + /** + * Runs the power transfer from the source to the destinations. pending rewrite + **/ + private fun runPowerTransfer(source: Node.NodePositionData, rawDestinations: List, availableTransferPower: Int): Int { + if (rawDestinations.isEmpty()) return availableTransferPower + + val filteredDestinations = rawDestinations.filter { destinationLoc -> + getInputEntities(holder.getWorld(), destinationLoc).any { it is PoweredMultiblockEntity && !it.powerStorage.isFull() } + } + + val numDestinations = filteredDestinations.size + + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(source, filteredDestinations[it]) + }.getOrNull() } + + var maximumResistance: Double = -1.0 + + // Perform the calc & max find in the same loop + val pathResistance: Array = Array(numDestinations) { + val res = calculatePathResistance(paths[it]) + if (res != null && maximumResistance < res) maximumResistance = res + + res + } + + // All null, no paths found + if (maximumResistance == -1.0) return availableTransferPower + + var shareFactorSum = 0.0 + + // Get a parallel array containing the ascending order of resistances + val sortedIndexes = getSorted(pathResistance) + + val shareFactors: Array = Array(numDestinations) { index -> + val resistance = pathResistance[index] ?: return@Array null + val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) + shareFactorSum += fac + + fac + } + + var remainingPower = availableTransferPower + + for ((index, destination) in filteredDestinations.withIndex()) { + val shareFactor = shareFactors[index] ?: continue + val inputData = PowerInputNode.getPoweredEntities(source.world, destination) + + val share = shareFactor / shareFactorSum + + val idealSend = (availableTransferPower * share).roundToInt() + val toSend = minOf(idealSend, getRemainingCapacity(inputData)) + + // Amount of power that didn't fit + val remainder = distributePower(inputData, toSend) + val realTaken = toSend - remainder + + remainingPower -= realTaken + completeChain(paths[index], realTaken) + + if (remainder == 0) continue + + // Get the proportion of the amount of power that sent compared to the ideal calculations. + val usedShare = realTaken.toDouble() / idealSend.toDouble() + // Use that to get a proportion of the share factor, and remove that from the sum. + val toRemove = shareFactor * usedShare + shareFactorSum -= toRemove + } + + return remainingPower + } } /** * Gets the powered entities accessible from this location, assuming it is an input + * This method is used in conjunction with input registration to allow direct access via signs, and remote access via registered inputs **/ -fun getPoweredEntities(world: World, location: BlockKey): Set { +fun getInputEntities(world: World, location: BlockKey): Set { val inputManager = world.ion.inputManager val registered = inputManager.getHolders(CacheType.POWER, location) + val block = getBlockIfLoaded(world, getX(location), getY(location), getZ(location)) ?: return setOf() + val adjacentBlocks = ADJACENT_BLOCK_FACES.mapNotNull { - val block = getBlockIfLoaded(world, getX(location), getY(location), getZ(location)) ?: return@mapNotNull null - val adjacent = block.getRelativeIfLoaded(it)?.state as? Sign ?: return@mapNotNull null - MultiblockEntities.getMultiblockEntity(adjacent) + val adjacent = block.getRelativeIfLoaded(it) + val data = adjacent?.blockData as? WallSign ?: return@mapNotNull null + MultiblockEntities.getMultiblockEntity(adjacent.x, adjacent.y, adjacent.z, world, data) } return registered.plus(adjacentBlocks) } +/** + * Distributes power to the provided list of entities + * Returns the amount that would not fit + **/ fun distributePower(destinations: List, power: Int): Int { val entities = destinations.filterTo(mutableListOf()) { !it.powerStorage.isFull() } if (entities.isEmpty()) return power @@ -141,74 +229,6 @@ fun distributePower(destinations: List, power: Int): In return remainingPower } -/** - * Runs the power transfer from the source to the destinations. pending rewrite - **/ -private fun runPowerTransfer(source: Node.NodePositionData, destinations: List, availableTransferPower: Int): Int { - if (destinations.isEmpty()) return availableTransferPower - - val numDestinations = destinations.size - - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, destinations[it]) - }.getOrNull() } - - var maximumResistance: Double = -1.0 - - // Perform the calc & max find in the same loop - val pathResistance: Array = Array(numDestinations) { - val res = calculatePathResistance(paths[it]) - if (res != null && maximumResistance < res) maximumResistance = res - - res - } - - // All null, no paths found - if (maximumResistance == -1.0) return availableTransferPower - - var shareFactorSum = 0.0 - - // Get a parallel array containing the ascending order of resistances - val sortedIndexes = getSorted(pathResistance) - - val shareFactors: Array = Array(numDestinations) { index -> - val resistance = pathResistance[index] ?: return@Array null - val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) - shareFactorSum += fac - - fac - } - - var remainingPower = availableTransferPower - - for ((index, destination) in destinations.withIndex()) { - val shareFactor = shareFactors[index] ?: continue - val inputData = PowerInputNode.getPoweredEntities(source.world, destination) - - val share = shareFactor / shareFactorSum - - val idealSend = (availableTransferPower * share).roundToInt() - val toSend = minOf(idealSend, getRemainingCapacity(inputData)) - - // Amount of power that didn't fit - val remainder = distributePower(inputData, toSend) - val realTaken = toSend - remainder - - remainingPower -= realTaken - completeChain(paths[index], realTaken) - - if (remainder == 0) continue - - // Get the proportion of the amount of power that sent compared to the ideal calculations. - val usedShare = realTaken.toDouble() / idealSend.toDouble() - // Use that to get a proportion of the share factor, and remove that from the sum. - val toRemove = shareFactor * usedShare - shareFactorSum -= toRemove - } - - return remainingPower -} - private fun getRemainingCapacity(destinations: List): Int { return destinations.sumOf { it.powerStorage.getRemainingCapacity() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 275dd3e1f0..dfc6c9210a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -2,14 +2,12 @@ package net.horizonsend.ion.server.features.transport.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.kyori.adventure.audience.Audience import org.bukkit.World import org.bukkit.block.BlockFace import java.util.PriorityQueue @@ -20,11 +18,11 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { return type.get(chunk).getOrCache(pos) } -inline fun getNetworkDestinations(cacheType: CacheType, world: World, originPos: BlockKey, check: (Node.NodePositionData) -> Boolean): LongOpenHashSet { - val originNode = getOrCacheNode(cacheType, world, originPos) ?: return LongOpenHashSet() +inline fun getNetworkDestinations(cacheType: CacheType, world: World, originPos: BlockKey, check: (Node.NodePositionData) -> Boolean): List { + val originNode = getOrCacheNode(cacheType, world, originPos) ?: return listOf() val visitQueue = ArrayDeque() - val visitedSet = LongOpenHashSet() + val visited = LongOpenHashSet() val destinations = LongOpenHashSet() visitQueue.addAll(originNode.getNextNodes( @@ -35,18 +33,14 @@ inline fun getNetworkDestinations(cacheType: CacheType, world: while (visitQueue.isNotEmpty()) { val current = visitQueue.removeFirst() - visitedSet.add(current.position) + visited.add(current.position) - if (current.type is T && check(current)) { - destinations.add(current.position) - } - - val next = current.getNextNodes().filterNot { visitedSet.contains(it.position) || visitQueue.contains(it) } + if (current.type is T && check(current)) destinations.add(current.position) - visitQueue.addAll(next) + visitQueue.addAll(current.getNextNodes().filterNot { visited.contains(it.position) || visitQueue.contains(it) }) } - return destinations + return destinations.toList() } /** @@ -95,6 +89,7 @@ fun getIdealPath(from: Node.NodePositionData, to: BlockKey): Array { - val transferable = current.node.getNextNodes().toList() - - audience?.information("${transferable.size} transferable nodes") +fun getNeighbors(current: PathfindingNodeWrapper): Array { + val transferable = current.node.getNextNodes() return Array(transferable.size) { val next = transferable[it] From 9da191661eaacb537a7999f43f9e8b08a9b51a9b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 14:22:18 -0600 Subject: [PATCH 289/500] synchronize cache access --- .../features/transport/nodes/cache/TransportCache.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index bc27e5ff9d..ed66068a58 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -14,15 +14,16 @@ import org.bukkit.block.Block abstract class TransportCache(val holder: CacheHolder<*> /* TODO temp network holder, works for now */) { private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() + private val mutex = Any() abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory abstract fun tickExtractor(location: BlockKey, delta: Double) - fun isCached(at: BlockKey): Boolean = cache.containsKey(at) + fun isCached(at: BlockKey): Boolean = synchronized(mutex) { cache.containsKey(at) } - fun getCached(at: BlockKey): Node? { + fun getCached(at: BlockKey): Node? = synchronized(mutex) { val state = cache[at] ?: return null return when (state) { is CacheState.Empty -> null @@ -41,7 +42,7 @@ abstract class TransportCache(val holder: CacheHolder<*> /* TODO temp network ho cache(location, block) } - fun cache(location: BlockKey, block: Block): Node? { + fun cache(location: BlockKey, block: Block): Node? = synchronized(mutex) { val type = nodeFactory.cache(block) val state = if (type == null) CacheState.Empty else CacheState.Present(type) @@ -49,11 +50,11 @@ abstract class TransportCache(val holder: CacheHolder<*> /* TODO temp network ho return type } - fun invalidate(x: Int, y: Int, z: Int) { + fun invalidate(x: Int, y: Int, z: Int) = synchronized(mutex) { invalidate(toBlockKey(x, y, z)) } - fun invalidate(key: BlockKey) { + fun invalidate(key: BlockKey) = synchronized(mutex) { (cache.remove(key) as? CacheState.Present)?.node?.onInvalidate() } From 79dd51108e3bda8e68839c2a82c804bfbbbd8b19 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 15:00:03 -0600 Subject: [PATCH 290/500] implement hacky fix for lag --- .../nodes/cache/PowerTransportCache.kt | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 7fba13f1bf..d94a942a7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -18,12 +18,8 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD import org.bukkit.Material.IRON_BLOCK @@ -35,7 +31,6 @@ import org.bukkit.Material.SPONGE import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.data.type.Observer -import org.bukkit.block.data.type.WallSign import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod import kotlin.math.roundToInt @@ -184,13 +179,8 @@ class PowerTransportCache(holder: CacheHolder) : TransportC fun getInputEntities(world: World, location: BlockKey): Set { val inputManager = world.ion.inputManager val registered = inputManager.getHolders(CacheType.POWER, location) - val block = getBlockIfLoaded(world, getX(location), getY(location), getZ(location)) ?: return setOf() - val adjacentBlocks = ADJACENT_BLOCK_FACES.mapNotNull { - val adjacent = block.getRelativeIfLoaded(it) - val data = adjacent?.blockData as? WallSign ?: return@mapNotNull null - MultiblockEntities.getMultiblockEntity(adjacent.x, adjacent.y, adjacent.z, world, data) - } + val adjacentBlocks = stupidOffsets.mapNotNull { MultiblockEntities.getMultiblockEntity(world, it.x, it.y, it.z) } return registered.plus(adjacentBlocks) } @@ -259,3 +249,27 @@ fun getSorted(pathResistance: Array): IntArray { return ranks } + +val stupidOffsets: Array = arrayOf( + // Upper ring + Vec3i(1, 1, 0), + Vec3i(-1, 1, 0), + Vec3i(0, 1, 1), + Vec3i(0, 1, -1), + // Lower ring + Vec3i(1, -1, 0), + Vec3i(-1, -1, 0), + Vec3i(0, -1, 1), + Vec3i(0, -1, -1), + + // Middle ring + Vec3i(2, 0, 0), + Vec3i(-2, 0, 0), + Vec3i(0, 0, -2), + Vec3i(0, 0, -2), + + Vec3i(1, 0, 1), + Vec3i(-1, 0, 1), + Vec3i(1, 0, -1), + Vec3i(-1, 0, -1), +) From 75a8b8f04dd5f31c22473e520395caca586eef74 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 18:11:17 -0600 Subject: [PATCH 291/500] Implement fluid nodes --- .../nodes/cache/FluidTransportCache.kt | 10 ++++ .../transport/nodes/cache/NodeCacheFactory.kt | 5 ++ .../transport/nodes/types/FluidNode.kt | 59 +++++++++++++++++++ .../transport/nodes/types/PowerNode.kt | 16 ++--- 4 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 5fe7946a71..f563336e51 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -1,12 +1,22 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Material +import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.FLUID override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addDataHandler(Material.LIGHTNING_ROD) { data, _ -> FluidNode.LightningRodNode(data.facing.axis) } + .addSimpleNode(Material.CRAFTING_TABLE, FluidNode.FluidExtractorNode) + .addSimpleNode(Material.FLETCHING_TABLE, FluidNode.FluidInputNode) + .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) + .addSimpleNode(Material.IRON_BLOCK, FluidNode.FluidMergeNode) + .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) .build() override fun tickExtractor(location: BlockKey, delta: Double) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index f9d1c94b24..621a16e161 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -33,6 +33,11 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map, node: Node): Builder { + for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } + return this + } + fun build(): NodeCacheFactory { return NodeCacheFactory(materialHandlers) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt new file mode 100644 index 0000000000..942a6f1a87 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt @@ -0,0 +1,59 @@ +package net.horizonsend.ion.server.features.transport.nodes.types + +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.faces +import org.bukkit.Axis +import org.bukkit.Material +import org.bukkit.block.BlockFace + +sealed interface FluidNode : Node { + override val cacheType: CacheType get() = CacheType.FLUID + + data class FluidJunctionNode(val channel: Material) : FluidNode { + override val pathfindingResistance: Double = 1.0 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = if (other is FluidJunctionNode) other.channel == channel else true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = if (other is FluidJunctionNode) other.channel == channel else true + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data class LightningRodNode(var axis: Axis) : FluidNode, ComplexNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis + override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) + override fun onTranslate(movement: StarshipMovement) { + this.axis = movement.displaceFace(this.axis.faces.first).axis + } + } + + data object FluidExtractorNode : FluidNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is FluidInputNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data object FluidInputNode : FluidNode { + override val pathfindingResistance: Double = 0.0 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data object FluidMergeNode : FluidNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is FluidJunctionNode + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is FluidJunctionNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + + data object FluidInvertedMergeNode : FluidNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is LightningRodNode + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is LightningRodNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 555c135585..35048b5d9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -47,6 +47,14 @@ sealed interface PowerNode : Node { override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } + data object PowerInputNode : PowerNode { + override val pathfindingResistance: Double = 0.0 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.POWER, location).filterIsInstance() + } + data object PowerMergeNode : PowerNode { override val pathfindingResistance: Double = 0.5 override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is SpongeNode @@ -128,12 +136,4 @@ sealed interface PowerNode : Node { private data class TransferredPower(val transferred: Int, val time: Long) } - - data object PowerInputNode : PowerNode { - override val pathfindingResistance: Double = 0.0 - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.POWER, location).filterIsInstance() - } } From b15bb3893c7817afc7e789472682d5c3d67fb1f6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 18:19:01 -0600 Subject: [PATCH 292/500] add fluid junction node w/ channels --- .../nodes/cache/FluidTransportCache.kt | 13 ++++++++++++- .../transport/nodes/cache/NodeCacheFactory.kt | 10 ++++++++++ .../server/miscellaneous/utils/Materials.kt | 18 ++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index f563336e51..db46735888 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -3,16 +3,27 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material +import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.Material.WAXED_CHISELED_COPPER +import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER +import org.bukkit.Material.WAXED_OXIDIZED_COPPER +import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.FLUID override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addDataHandler(Material.LIGHTNING_ROD) { data, _ -> FluidNode.LightningRodNode(data.facing.axis) } - .addSimpleNode(Material.CRAFTING_TABLE, FluidNode.FluidExtractorNode) + .addSimpleNode(WAXED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_CHISELED_COPPER) } + .addSimpleNode(WAXED_EXPOSED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_EXPOSED_CHISELED_COPPER) } + .addSimpleNode(WAXED_WEATHERED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_WEATHERED_CHISELED_COPPER) } + .addSimpleNode(WAXED_OXIDIZED_COPPER) { FluidNode.FluidJunctionNode(WAXED_OXIDIZED_COPPER) } + .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { FluidNode.FluidJunctionNode(CRAFTING_TABLE) } + .addSimpleNode(CRAFTING_TABLE, FluidNode.FluidExtractorNode) .addSimpleNode(Material.FLETCHING_TABLE, FluidNode.FluidInputNode) .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) .addSimpleNode(Material.IRON_BLOCK, FluidNode.FluidMergeNode) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 621a16e161..2dfee0d690 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -28,6 +28,16 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map, constructor: (BlockKey) -> Node): Builder { + for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, key -> constructor(key) } + return this + } + + fun addSimpleNode(material: Material, constructor: (BlockKey) -> Node): Builder { + this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, key -> constructor(key) } + return this + } + fun addSimpleNode(material: Material, node: Node): Builder { this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } return this diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt index bb140164ca..1b1dbc5929 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Materials.kt @@ -154,7 +154,7 @@ val COPPER_BULB_TYPES = enumSetOf( val Material.isCopperBulb get() = COPPER_BULB_TYPES.contains(this) -val CHISELED_COPPER_TYPES = enumSetOf( +val ALL_CHISELED_COPPER_TYPES = enumSetOf( Material.CHISELED_COPPER, Material.EXPOSED_CHISELED_COPPER, Material.WEATHERED_CHISELED_COPPER, @@ -165,4 +165,18 @@ val CHISELED_COPPER_TYPES = enumSetOf( Material.WAXED_OXIDIZED_CHISELED_COPPER ) -val Material.isChiseledCopper get() = CHISELED_COPPER_TYPES.contains(this) +val WAXED_CHISELED_COPPER_TYPES = enumSetOf( + Material.WAXED_CHISELED_COPPER, + Material.WAXED_EXPOSED_CHISELED_COPPER, + Material.WAXED_WEATHERED_CHISELED_COPPER, + Material.WAXED_OXIDIZED_CHISELED_COPPER +) + +val UNWAXED_CHISELED_COPPER_TYPES = enumSetOf( + Material.CHISELED_COPPER, + Material.EXPOSED_CHISELED_COPPER, + Material.WEATHERED_CHISELED_COPPER, + Material.OXIDIZED_CHISELED_COPPER, +) + +val Material.isChiseledCopper get() = ALL_CHISELED_COPPER_TYPES.contains(this) From 6d24156480cfa7d374cdf4110d92b9565e9ed769 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 13 Nov 2024 18:38:58 -0600 Subject: [PATCH 293/500] fix + util --- .../nodes/cache/FluidTransportCache.kt | 21 +++++++++++++++++++ .../nodes/cache/PowerTransportCache.kt | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index db46735888..b9e50c58f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -1,17 +1,21 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.WAXED_CHISELED_COPPER import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER +import org.bukkit.World import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { @@ -31,6 +35,23 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .build() override fun tickExtractor(location: BlockKey, delta: Double) { + println("Delta: $delta") + } + + private fun getPowerExtractorSourcePool(extractorLocation: BlockKey, world: World): List { + val sources = mutableListOf() + + for (face in ADJACENT_BLOCK_FACES) { + val inputLocation = getRelative(extractorLocation, face) + if (holder.getOrCacheGlobalNode(inputLocation) !is FluidNode.FluidInputNode) continue + val entities = getInputEntities(world, inputLocation) + + for (entity in entities) { + if (entity !is FluidStoringEntity) continue + sources.add(entity) + } + } + return sources } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index d94a942a7e..fafb91c548 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -81,7 +81,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC } }} - fun getPowerExtractorSourcePool(extractorLocation: BlockKey, world: World): List { + private fun getPowerExtractorSourcePool(extractorLocation: BlockKey, world: World): List { val sources = mutableListOf() for (face in ADJACENT_BLOCK_FACES) { @@ -91,7 +91,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC for (entity in entities) { if (entity !is PoweredMultiblockEntity) continue - if (entity.powerStorage.isFull()) continue + if (entity.powerStorage.isEmpty()) continue sources.add(entity) } } From 2967aaa7e8897c0b5d210a0614e5c09ada2b7596 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 14 Nov 2024 11:30:03 -0600 Subject: [PATCH 294/500] Utility functions for fluid transfer, additional capabilities --- .../display/fluid/ComplexFluidDisplay.kt | 4 +-- .../entity/type/fluids/FluidStoringEntity.kt | 15 +++++++++- .../CategoryRestrictedInternalStorage.kt | 3 +- .../type/fluids/storage/InternalStorage.kt | 4 +++ .../type/fluids/storage/SingleFluidStorage.kt | 2 +- .../storage/UnlimitedInternalStorage.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 6 ++-- .../collector/PipedGasCollectorMultiblock.kt | 10 +++---- .../fluid/storage/FluidStorageMultiblock.kt | 3 +- .../transport/TransportConfiguration.kt | 3 +- .../nodes/cache/FluidTransportCache.kt | 29 ++++++++++++++++--- 11 files changed, 61 insertions(+), 20 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt index 618a761d04..ee34adeacd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt @@ -6,13 +6,13 @@ import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline class ComplexFluidDisplay( - storage: StorageContainer, + container: StorageContainer, val title: Component, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float -) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { +) : FluidDisplay(container, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { return ofChildren(title, newline(), formatFluid()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 7845c18391..217bc16685 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -15,7 +15,6 @@ import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { val capacities: Array - val fluidInputOffsets: Array fun getFluidInputLocations(): Set { @@ -28,13 +27,27 @@ interface FluidStoringEntity { **/ fun canStore(fluid: PipedFluid, amount: Int) = capacities.any { it.internalStorage.canStore(fluid, amount) } + fun canStore(fluid: PipedFluid) = capacities.any { it.internalStorage.canStore(fluid, 0) } + /** * Returns the first internal storage that can contain the amount of the fluid provided. **/ fun firstCasStore(fluid: PipedFluid, amount: Int): StorageContainer? = capacities.firstOrNull { it.internalStorage.canStore(fluid, amount) } + fun firstCasStore(fluid: PipedFluid): StorageContainer? = capacities.firstOrNull { it.internalStorage.canStore(fluid, 0) } + + fun getCapacityFor(fluid: PipedFluid): Int { + return capacities.sumOf { if (it.internalStorage.canStore(fluid, 0)) it.internalStorage.remainingCapacity() else 0} + } + fun isFull(): Boolean = capacities.all { it.internalStorage.isFull() } + fun isEmpty() = capacities.all { it.internalStorage.isEmpty() } + + fun canExtractAny(): Boolean = capacities.any { !it.internalStorage.isEmpty() } + + fun canStoreAny(): Boolean = capacities.any { !it.internalStorage.isFull() && it.internalStorage.inputAllowed } + /** * Adds the amount of the fluid to the first available internal storage **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt index c3f0ebdd18..8877a19ce8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt @@ -5,7 +5,8 @@ import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCate class CategoryRestrictedInternalStorage( private val storageCapacity: Int, - private vararg val allowedCategories: FluidCategory + override val inputAllowed: Boolean, + private vararg val allowedCategories: FluidCategory, ) : InternalStorage() { override fun getCapacity(): Int = storageCapacity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt index 1418589a1c..e58db7f3b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt @@ -15,8 +15,12 @@ abstract class InternalStorage { protected var amountUnsafe: Int = 0 protected open var fluidUnsafe: PipedFluid? = null + abstract val inputAllowed: Boolean + abstract fun getCapacity(): Int + fun remainingCapacity() = getCapacity() - getAmount() + abstract fun canStore(resource: PipedFluid, liters: Int): Boolean fun isEmpty(): Boolean = getStoredFluid() == null || getAmount() == 0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt index 0165bed0b4..fc9c64320f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storag import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -class SingleFluidStorage(private val storageCapacity: Int, private val restrictedFluid: PipedFluid) : InternalStorage() { +class SingleFluidStorage(private val storageCapacity: Int, private val restrictedFluid: PipedFluid, override val inputAllowed: Boolean) : InternalStorage() { override var fluidUnsafe: PipedFluid? = restrictedFluid override fun getCapacity(): Int = storageCapacity diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt index 7d38a67129..0abe329316 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.features.transport.fluids.PipedFluid /** * Internal storage with no limits on what fluid can be stored **/ -class UnlimitedInternalStorage(private val storageCapacity: Int) : InternalStorage() { +class UnlimitedInternalStorage(private val storageCapacity: Int, override val inputAllowed: Boolean) : InternalStorage() { override fun getCapacity(): Int = storageCapacity override fun canStore(resource: PipedFluid, liters: Int): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index b98c737bde..f0f2f21615 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -213,9 +213,9 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf( - loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER)), - loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN)), - loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN)) + loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER, true)), + loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN, false)), + loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN, false)) ) private val hydrogenStorage by lazy { getNamedStorage("hydrogen_tank") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt index a165c13f61..ff72fe8376 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/PipedGasCollectorMultiblock.kt @@ -56,9 +56,9 @@ object PipedGasCollectorMultiblock : Multiblock(), x(+1).lightningRod() } y(-1) { - x(-1).anyStairs() + x(-1).extractor() x(0).fluidInput() - x(+1).anyStairs() + x(+1).extractor() } } z(+1) { @@ -112,9 +112,9 @@ object PipedGasCollectorMultiblock : Multiblock(), override val fluidInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) override val capacities: Array = arrayOf( - loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, GAS)), - loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, GAS)), - loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, GAS)), + loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, false, GAS)), + loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, false, GAS)), + loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, false, GAS)), ) override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 2d908ed270..66b73866b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -44,7 +44,7 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM z: Int, world: World, structureDirection: BlockFace, - ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity)), FluidStoringEntity, DisplayMultiblockEntity { + ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity, true)), FluidStoringEntity, DisplayMultiblockEntity { override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, @@ -63,6 +63,7 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM override fun handleRemoval() { releaseInputs(CacheType.FLUID, getFluidInputLocations()) + } override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt index 848b3004bd..0b81d93994 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt @@ -9,6 +9,7 @@ data class TransportConfiguration( @Serializable data class ExtractorConfiguration( val extractorTickIntervalMS: Long = 2000, - val maxPowerRemovedPerExtractorTick: Int = 1000 + val maxPowerRemovedPerExtractorTick: Int = 1000, + val maxFluidRemovedPerExtractorTick: Int = 1000, ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index b9e50c58f5..ec8762c994 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -1,9 +1,13 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis @@ -17,16 +21,20 @@ import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.World import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod +import kotlin.math.roundToInt class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.FLUID override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addDataHandler(Material.LIGHTNING_ROD) { data, _ -> FluidNode.LightningRodNode(data.facing.axis) } + .addSimpleNode(WAXED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_CHISELED_COPPER) } .addSimpleNode(WAXED_EXPOSED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_EXPOSED_CHISELED_COPPER) } .addSimpleNode(WAXED_WEATHERED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_WEATHERED_CHISELED_COPPER) } .addSimpleNode(WAXED_OXIDIZED_COPPER) { FluidNode.FluidJunctionNode(WAXED_OXIDIZED_COPPER) } + .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { FluidNode.FluidJunctionNode(CRAFTING_TABLE) } + .addSimpleNode(CRAFTING_TABLE, FluidNode.FluidExtractorNode) .addSimpleNode(Material.FLETCHING_TABLE, FluidNode.FluidInputNode) .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) @@ -34,11 +42,24 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) .build() - override fun tickExtractor(location: BlockKey, delta: Double) { - println("Delta: $delta") - } + override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { + val world = holder.getWorld() + val sources = getFluidExtractorSourcePool(location, world) + val source = sources.randomOrNull() ?: return@submit //TODO take from all + + if (source.getStoredResources().isEmpty()) return@submit + + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(CacheType.POWER, world, location) { node -> + world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } + } + + if (destinations.isEmpty()) return@submit + + val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxFluidRemovedPerExtractorTick * delta).roundToInt() + } } - private fun getPowerExtractorSourcePool(extractorLocation: BlockKey, world: World): List { + private fun getFluidExtractorSourcePool(extractorLocation: BlockKey, world: World): List { val sources = mutableListOf() for (face in ADJACENT_BLOCK_FACES) { From a7e9b06e20e037e940efb50885576fc7f1d7eeae Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 14 Nov 2024 12:28:25 -0600 Subject: [PATCH 295/500] Add holder to text display handler for reliability --- .../client/display/modular/DisplayHandlerHolder.kt | 5 +++++ .../features/client/display/modular/DisplayHandlers.kt | 4 +++- .../features/client/display/modular/TextDisplayHandler.kt | 6 ++++++ .../server/features/multiblock/entity/MultiblockEntity.kt | 4 +++- .../ion/server/features/transport/nodes/types/PowerNode.kt | 7 ++++++- 5 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt new file mode 100644 index 0000000000..bfca4d8b14 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.client.display.modular + +interface DisplayHandlerHolder { + val isAlive: Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index 988eff728d..07b4fb15ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -25,6 +25,7 @@ object DisplayHandlers : IonServerComponent() { val signDirection = entity.structureDirection.oppositeFace return TextDisplayHandler( + entity, entity.world, entity.x.toDouble() + 0.5, entity.y.toDouble() + 0.4, @@ -37,7 +38,7 @@ object DisplayHandlers : IonServerComponent() { ) } - fun newBlockOverlay(world: World, block: Vec3i, direction: BlockFace, vararg display: Display): TextDisplayHandler { + fun newBlockOverlay(holder: DisplayHandlerHolder, world: World, block: Vec3i, direction: BlockFace, vararg display: Display): TextDisplayHandler { val facingBlock = getRelative(toBlockKey(block), direction) val x = getX(facingBlock).toDouble() + 0.5 @@ -45,6 +46,7 @@ object DisplayHandlers : IonServerComponent() { val z = getZ(facingBlock).toDouble() + 0.5 return TextDisplayHandler( + holder, world, x, y, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index 1606e34c4d..d8ba58c803 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -11,6 +11,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace class TextDisplayHandler( + val holder: DisplayHandlerHolder, var world: World, var anchorX: Double, var anchorY: Double, @@ -24,6 +25,11 @@ class TextDisplayHandler( val displays = listOf(*display) fun update() { + if (!holder.isAlive) { + remove() + return + } + displays.forEach { it.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 43d2d34235..92265fed32 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager @@ -44,7 +45,7 @@ abstract class MultiblockEntity( var world: World, var structureDirection: BlockFace -): PDCSerializable { +): PDCSerializable, DisplayHandlerHolder { private var lastRetrieved = System.currentTimeMillis() /** Gets the time since this value was last retrieved */ @@ -58,6 +59,7 @@ abstract class MultiblockEntity( /** Mark this entity as having been removed */ var removed: Boolean = false + final override val isAlive: Boolean get() = !removed override val persistentDataType: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion val position: BlockKey get() = toBlockKey(x, y, z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 35048b5d9f..500dabc3bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity @@ -69,8 +70,11 @@ sealed interface PowerNode : Node { override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexNode { + data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { + override var isAlive: Boolean = true + val displayHandler = DisplayHandlers.newBlockOverlay( + this, cache.holder.getWorld(), toVec3i(location), face, @@ -126,6 +130,7 @@ sealed interface PowerNode : Node { override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) override fun onInvalidate() { + isAlive = false displayHandler.remove() } From 579a64a311934089b8079ed50c1bbceb7f729c58 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 14 Nov 2024 13:01:46 -0600 Subject: [PATCH 296/500] add item requirement to multiblock shape --- .../multiblock/shape/BlockRequirement.kt | 9 +++- .../multiblock/shape/MultiblockShape.kt | 45 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index b66e2b1325..e88983f73c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -4,12 +4,14 @@ import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData +import org.bukkit.inventory.ItemStack class BlockRequirement( val alias: String, var example: (BlockFace) -> BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, - private val dataCheck: (BlockData) -> Boolean + private val dataCheck: (BlockData) -> Boolean, + val itemRequirement: ItemRequirement ) { operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) @@ -26,4 +28,9 @@ class BlockRequirement( return this } + + class ItemRequirement( + val itemCheck: (ItemStack) -> Boolean, + val consumeItem: (ItemStack) -> Boolean + ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index c144503886..67afb0e8e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -7,6 +7,8 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUI import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING +import net.horizonsend.ion.server.features.custom.items.CustomBlockItem +import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes @@ -230,7 +232,11 @@ class MultiblockShape { alias = type.toString(), example = { type.createBlockData() }, syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, - dataCheck = { type == it.material } + dataCheck = { type == it.material }, + itemRequirement = BlockRequirement.ItemRequirement( + itemCheck = { type == it.type }, + consumeItem = { it.amount-- >= 0 } + ) ) complete(requirement) @@ -245,7 +251,11 @@ class MultiblockShape { syncCheck = { block, _, loadChunks -> typeSet.contains(if (loadChunks) block.type else block.getTypeSafe() ?: return@BlockRequirement false) }, - dataCheck = { typeSet.contains(it.material) } + dataCheck = { typeSet.contains(it.material) }, + itemRequirement = BlockRequirement.ItemRequirement( + itemCheck = { typeSet.contains(it.type) }, + consumeItem = { it.amount-- >= 0 } + ) ) complete(requirement) @@ -262,7 +272,11 @@ class MultiblockShape { getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } } === customBlock }, - dataCheck = { CustomBlocks.getByBlockData(it) == customBlock } + dataCheck = { CustomBlocks.getByBlockData(it) == customBlock }, + itemRequirement = BlockRequirement.ItemRequirement( + itemCheck = { val customItem = it.customItem; customItem is CustomBlockItem && customItem.getCustomBlock() == customBlock }, + consumeItem = { it.amount-- >= 0 } + ) ) complete(requirement) @@ -319,9 +333,17 @@ class MultiblockShape { val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) blockData is Slab && blockData.type == DOUBLE }, - dataCheck = { it is Slab && it.type == DOUBLE } + dataCheck = { it is Slab && it.type == DOUBLE }, + itemRequirement = BlockRequirement.ItemRequirement( + itemCheck = { (it.type.isSlab && it.amount >= 2) }, + consumeItem = { + it.amount -= 2 + it.amount >= 0 + } + ), ) ) + fun anySlabOrStairs() = filteredTypes("any slab or stairs") { it.isSlab || it.isStairs } fun terracottaOrDoubleslab() { @@ -334,7 +356,14 @@ class MultiblockShape { (blockData is Slab && blockData.type == DOUBLE) || TERRACOTTA_TYPES.contains(blockType) }, - dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta } + dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta }, + itemRequirement = BlockRequirement.ItemRequirement( + itemCheck = { (it.type.isSlab && it.amount >= 2) || it.type.isTerracotta }, + consumeItem = { + if (it.type.isSlab) it.amount -= 2 else it.amount-- + it.amount >= 0 + } + ), ) } @@ -468,7 +497,11 @@ class MultiblockShape { val facing = blockData.getValue(AbstractFurnaceBlock.FACING).blockFace return@check facing == inward.oppositeFace }, - dataCheck = { it is Furnace } + dataCheck = { it is Furnace }, + itemRequirement = BlockRequirement.ItemRequirement( + itemCheck = { it.type == Material.FURNACE }, + consumeItem = { it.amount-- >= 0 } + ) )) fun solidBlock() = anyType( From e3c6c402eff63f8b0b75520014420d3d95f4e670 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Nov 2024 10:48:57 -0600 Subject: [PATCH 297/500] Add multiblock workbench --- .../features/custom/blocks/CustomBlocks.kt | 2 ++ .../custom/blocks/MultiblockWorkbench.kt | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index be85759a17..120624f7a6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -202,6 +202,8 @@ object CustomBlocks { return customItem.map { item -> listOf(item.constructItemStack(amount)) } } + val MULTIBLOCK_WORKBENCH = register(MultiblockWorkbench) + private fun customItemDrop(identifier: String, amount: Int = 1): Supplier> { val customItem = CustomItemRegistry.getByIdentifier(identifier)?.constructItemStack() ?: return Supplier { listOf() } customItem.amount = amount diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt new file mode 100644 index 0000000000..4e131ac075 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -0,0 +1,32 @@ +package net.horizonsend.ion.server.features.custom.blocks + +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop +import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import java.util.concurrent.TimeUnit + +object MultiblockWorkbench : InteractableCustomBlock( + identifier = "MULTIBLOCK_WORKBENCH", + blockData = CustomBlocks.mushroomBlockData(setOf(BlockFace.NORTH, BlockFace.DOWN, BlockFace.EAST)), + drops = BlockLoot( + requiredTool = null, + drops = customItemDrop(CustomItems::MULTIBLOCK_WORKBENCH, 1) + ) +) { + private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) + + override fun onRightClick(event: PlayerInteractEvent, block: Block) { + val player = event.player + cooldown.tryExec(player) { openMenu(player) } + } + + private fun openMenu(player: Player) { + + } + + +} From 452d730b749116307eb1c7ce4083940910d0c635 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Nov 2024 11:04:55 -0600 Subject: [PATCH 298/500] Abstract out tool mod menu --- .../items/type/tool/mods/ToolModMenu.kt | 149 ++---------------- .../gui/interactable/InteractableGUI.kt | 5 +- .../miscellaneous/registrations/Listeners.kt | 6 +- 3 files changed, 23 insertions(+), 137 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt index e02e37ca16..58c7e31028 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt @@ -6,46 +6,32 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.component.ModManager +import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.listener.SLEventListener -import org.bukkit.Material.AIR import org.bukkit.entity.Player import org.bukkit.event.EventHandler -import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.InventoryCloseEvent -import org.bukkit.event.inventory.InventoryDragEvent import org.bukkit.event.inventory.InventoryInteractEvent -import org.bukkit.event.inventory.InventoryType import org.bukkit.event.player.PlayerDropItemEvent import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryHolder import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack -import java.util.UUID import kotlin.math.ceil class ToolModMenu( - private val viewer: Player, + viewer: Player, private val itemStack: ItemStack, private val customItem: CustomItem, private val modManager: ModManager -) : InventoryHolder { - private val inventorySize = (ceil((modManager.getMods(itemStack).size + 1).toDouble() / 9.0) * 9).toInt() - private val internalInventory = IonServer.server.createInventory(this, inventorySize) +) : InteractableGUI(viewer) { + override val inventorySize = (ceil((modManager.getMods(itemStack).size + 1).toDouble() / 9.0) * 9).toInt() + override val internalInventory: Inventory = IonServer.server.createInventory(this, inventorySize) override fun getInventory(): Inventory = internalInventory - fun open() { - // Will return CRAFTING if none is open - if (viewer.openInventory.type != InventoryType.CRAFTING && viewer.openInventory.type != InventoryType.CREATIVE) return - - val view = viewer.openInventory(internalInventory) ?: return - - setup(view) - } - - private fun setup(view: InventoryView) { + override fun setup(view: InventoryView) { view.title = "Tool Modifications" populateMods() @@ -76,7 +62,7 @@ class ToolModMenu( val mods = contents .mapNotNull { it?.customItem } - .filterIsInstance() + .filterIsInstance() .mapTo(mutableSetOf()) { it.modification } .plus(nonItemMods) .toTypedArray() @@ -99,73 +85,11 @@ class ToolModMenu( /** * Fired when the inventory is closed **/ - fun handleClose(event: InventoryCloseEvent) { + override fun handleClose(event: InventoryCloseEvent) { rebuildFromContents() } - /** - * Events from the player's clicked inventory while the mod menu is on top - **/ - fun handlePlayerClick(event: InventoryClickEvent) { - val currentItem = event.currentItem - val cursorItem = event.cursor - val index = event.slot - - if (event.click != ClickType.SHIFT_LEFT && event.click != ClickType.SHIFT_RIGHT) return - - when { - currentItem != null && cursorItem.type == AIR -> handleAddItem(index, currentItem, event) - currentItem == null && cursorItem.type != AIR -> handleRemoveItem(index, event) - else -> event.isCancelled = true - } - } - - /** - * Events from the player's clicked mod menu - **/ - fun handleClick(event: InventoryClickEvent) { - val currentItem = event.currentItem - val cursorItem = event.cursor - val index = event.slot - - if (event.isCancelled) return - - when { - event.click == ClickType.NUMBER_KEY -> handleNumberKey(index, currentItem, event) - currentItem == null && cursorItem.type != AIR -> handleAddItem(index, cursorItem, event) - currentItem != null && cursorItem.type == AIR -> handleRemoveItem(index, event) - currentItem != null && cursorItem.type != AIR -> handleSwapItem(index, currentItem, cursorItem, event) - else -> event.isCancelled = true - } - } - - fun handleDrag(event: InventoryDragEvent) { - // If dragging something outside the inventory - if (event.rawSlots.none { it < inventorySize }) return - - when { - // Unstackable item can't be split across multiple slots - event.cursor == null && event.oldCursor.maxStackSize == 1 -> { - // Will only end up in a single slot - val slot = event.rawSlots.first() - handleAddItem(slot, event.newItems[slot]!!, event) - } - else -> event.isCancelled = true - } - } - - private fun handleNumberKey(slotNumber: Int, currentItem: ItemStack?, event: InventoryClickEvent) { - val playerItem = viewer.inventory.getItem(event.hotbarButton) ?: ItemStack(AIR) - - when { - currentItem == null && playerItem.type != AIR -> handleAddItem(slotNumber, playerItem, event) - currentItem != null && playerItem.type == AIR -> handleRemoveItem(slotNumber, event) - currentItem != null && playerItem.type != AIR -> handleSwapItem(slotNumber, currentItem, playerItem, event) - else -> event.isCancelled = true - } - } - - private fun handleAddItem(slot: Int, item: ItemStack, event: InventoryInteractEvent) { + override fun handleAddItem(slot: Int, item: ItemStack, event: InventoryInteractEvent) { if (!canAdd(item, event.whoClicked as Player)) { event.isCancelled = true return @@ -174,12 +98,12 @@ class ToolModMenu( rebuildFromContents(listOf(*internalInventory.contents, item)) } - private fun handleRemoveItem(slot: Int, event: InventoryClickEvent) { + override fun handleRemoveItem(slot: Int, event: InventoryClickEvent) { // Rebuild with the item removed rebuildFromContents(internalInventory.contents.subtract(setOf(internalInventory.contents[slot]))) } - private fun handleSwapItem(slot: Int, currentItem: ItemStack, new: ItemStack, event: InventoryClickEvent) { + override fun handleSwapItem(slot: Int, currentItem: ItemStack, new: ItemStack, event: InventoryClickEvent) { if (!canAdd(new, event.playerClicker)) { event.isCancelled = true return @@ -227,55 +151,12 @@ class ToolModMenu( } companion object : SLEventListener() { - private val inventories = mutableMapOf() - - fun create(viewer: Player, itemStack: ItemStack, customItem: CustomItem, manager: ModManager): net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu { - val holder = net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu(viewer, itemStack, customItem, manager) - net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu.Companion.inventories[viewer.uniqueId] = holder + fun create(viewer: Player, itemStack: ItemStack, customItem: CustomItem, manager: ModManager): ToolModMenu { + val holder = ToolModMenu(viewer, itemStack, customItem, manager) + setInventory(viewer.uniqueId, holder) return holder - } - - @EventHandler - fun onInventoryClick(event: InventoryClickEvent) { - val inventory = event.clickedInventory ?: return - - val holder = inventory.holder - if (holder is net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu) { - holder.handleClick(event) - } - - if (holder is Player) { - val topHolder = holder.openInventory.topInventory.holder - - if (topHolder is net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu) { - topHolder.handlePlayerClick(event) - } - - return - } - } - - @EventHandler - fun onInventoryDrag(event: InventoryDragEvent) { - val inventory = event.inventory - - val holder = inventory.holder - - if (holder is net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu) { - holder.handleDrag(event) - } - } - - @EventHandler - fun onInventoryClose(event: InventoryCloseEvent) { - val inventory = event.inventory - val holder = inventory.holder - - if (holder is net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu) { - holder.handleClose(event) - } } @EventHandler @@ -283,7 +164,7 @@ class ToolModMenu( val player = event.player val holder = player.openInventory.topInventory.holder - if (holder is net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu) { + if (ToolModMenu) { // Assume they dropped the item if (event.itemDrop.itemStack.itemMeta == holder.itemStack.itemMeta) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt index 0bc0348c27..dbce808e78 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt @@ -24,7 +24,7 @@ import org.bukkit.inventory.ItemStack import java.util.UUID import java.util.function.Consumer -abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { +abstract class InteractableGUI(val viewer: Player) : InventoryHolder { protected abstract val internalInventory: Inventory abstract val inventorySize: Int @@ -56,6 +56,7 @@ abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { abstract fun handleClose(event: InventoryCloseEvent) + abstract fun handleAddItem(slot: Int, item: ItemStack, event: InventoryInteractEvent) abstract fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean abstract fun canRemove(slot: Int, player: Player): Boolean abstract fun itemChanged(changedSlot: Int, changedItem: ItemStack) @@ -66,9 +67,11 @@ abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { return } + abstract fun handleRemoveItem(slot: Int, event: InventoryClickEvent) itemChanged(slot, item) } + abstract fun handleSwapItem(slot: Int, currentItem: ItemStack, new: ItemStack, event: InventoryClickEvent) open fun handleRemoveItem(slot: Int, event: InventoryClickEvent) { buttons[slot]?.accept(event) if (lockedSlots.contains(slot) || !canRemove(slot, event.whoClicked as Player)) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 09cf4e98e0..12f6489b66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -5,7 +5,8 @@ import net.horizonsend.ion.server.features.client.networking.packets.WorldPacket import net.horizonsend.ion.server.features.custom.blocks.CustomBlockListeners import net.horizonsend.ion.server.features.custom.items.CustomItemListeners import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporterManager -import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners +import net.horizonsend.ion.server.features.custom.items.mods.ToolModMenu +import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListenersb import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam @@ -77,7 +78,8 @@ val listeners: List = listOf( BiomeFixer9001(), AbstractTractorBeam.Companion, PlayerDeathListener, - net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu, + ToolModMenu, + InteractableGUI, RecipeModifications, ActivePlayerController.Companion, TransportManager, From c3a4396b80d8479309f6182927abe7379ba57acf Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Nov 2024 11:14:35 -0600 Subject: [PATCH 299/500] add util for component inventory names --- .../features/custom/items/type/tool/mods/ToolModMenu.kt | 3 ++- .../ion/server/features/gui/interactable/InteractableGUI.kt | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt index 58c7e31028..467cba0f69 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.custom.items.component.ModManager import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.listener.SLEventListener +import net.kyori.adventure.text.Component.text import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.inventory.InventoryClickEvent @@ -32,7 +33,7 @@ class ToolModMenu( override fun getInventory(): Inventory = internalInventory override fun setup(view: InventoryView) { - view.title = "Tool Modifications" + view.setTitle(text("Tool Modifications")) populateMods() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt index dbce808e78..0bc0348c27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt @@ -24,7 +24,7 @@ import org.bukkit.inventory.ItemStack import java.util.UUID import java.util.function.Consumer -abstract class InteractableGUI(val viewer: Player) : InventoryHolder { +abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { protected abstract val internalInventory: Inventory abstract val inventorySize: Int @@ -56,7 +56,6 @@ abstract class InteractableGUI(val viewer: Player) : InventoryHolder { abstract fun handleClose(event: InventoryCloseEvent) - abstract fun handleAddItem(slot: Int, item: ItemStack, event: InventoryInteractEvent) abstract fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean abstract fun canRemove(slot: Int, player: Player): Boolean abstract fun itemChanged(changedSlot: Int, changedItem: ItemStack) @@ -67,11 +66,9 @@ abstract class InteractableGUI(val viewer: Player) : InventoryHolder { return } - abstract fun handleRemoveItem(slot: Int, event: InventoryClickEvent) itemChanged(slot, item) } - abstract fun handleSwapItem(slot: Int, currentItem: ItemStack, new: ItemStack, event: InventoryClickEvent) open fun handleRemoveItem(slot: Int, event: InventoryClickEvent) { buttons[slot]?.accept(event) if (lockedSlots.contains(slot) || !canRemove(slot, event.whoClicked as Player)) { From f5d354bec0847d204636b0408d5c95561cc553f1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Nov 2024 12:45:07 -0600 Subject: [PATCH 300/500] further abstraction, work on the workbench --- .../custom/blocks/MultiblockWorkbench.kt | 93 ++++++++++++++++++- .../items/type/tool/mods/ToolModMenu.kt | 14 ++- 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 4e131ac075..549640f555 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,12 +1,28 @@ package net.horizonsend.ion.server.features.custom.blocks +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.gui.GuiItem +import net.horizonsend.ion.server.features.gui.GuiText +import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI +import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown +import net.horizonsend.ion.server.miscellaneous.utils.text.itemName +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.Location +import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.BlockFace import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.InventoryView +import org.bukkit.inventory.ItemStack import java.util.concurrent.TimeUnit object MultiblockWorkbench : InteractableCustomBlock( @@ -18,15 +34,86 @@ object MultiblockWorkbench : InteractableCustomBlock( ) ) { private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) + private var multiblockIndex = 0 + val multiblocks = MultiblockRegistration.getAllMultiblocks().toList() override fun onRightClick(event: PlayerInteractEvent, block: Block) { val player = event.player - cooldown.tryExec(player) { openMenu(player) } - } - private fun openMenu(player: Player) { + cooldown.tryExec(player) { openMenu(player, block.location.toCenterLocation()) } + } + private fun openMenu(player: Player, location: Location) { + val inv = MultiblockWorkbenchMenu(player, location) + InteractableGUI.setInventory(player.uniqueId, inv) + inv.open() } + class MultiblockWorkbenchMenu(viewer: Player, val location: Location): InteractableGUI(viewer) { + override val inventorySize = 36 + override val internalInventory: Inventory = IonServer.server.createInventory(this, inventorySize) + + override fun setup(view: InventoryView) { + val text = GuiText("Multiblock Workbench") + text.add(text("Missing Materials! [Hover]", NamedTextColor.RED), line = 0) + text.setSlotOverlay( + "# # # # # # # # #", + "# # # . . . . . .", + "# . # . . . . . .", + "# # # . . . . . ." + ) + + addGuiButton(18, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + it.setCustomModelData(GuiItem.LEFT.customModelData) + it.displayName(text("Previous Multiblock").itemName) + }) { + multiblockIndex = (multiblockIndex - 1).coerceAtLeast(0) + updateMultiblock() + } + + addGuiButton(20, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + it.setCustomModelData(GuiItem.RIGHT.customModelData) + it.displayName(text("Next Multiblock").itemName) + }) { + multiblockIndex = (multiblockIndex + 1).coerceAtMost(multiblocks.lastIndex) + updateMultiblock() + } + + noDropSlots.add(19) + + view.setTitle(text.build()) + } + private fun updateMultiblock() { + val atIndex = multiblocks[multiblockIndex] + viewer.information(atIndex.toString()) + } + + private fun isLockedSlot(slot: Int): Boolean { + if (slot in 0..11) return true + if (slot in 18..20) return true + return slot in 27..29 + } + + override fun getInventory(): Inventory { + return internalInventory + } + + override fun itemChanged(changedSlot: Int, changedItem: ItemStack) {} + + override fun canRemove(slot: Int, player: Player): Boolean { + return !isLockedSlot(slot) + } + + override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { + return !isLockedSlot(slot) + } + + override fun handleClose(event: InventoryCloseEvent) { + for ((slot, content) in inventory.contents.withIndex()) { + if (noDropSlots.contains(slot)) continue + viewer.world.dropItemNaturally(location, content ?: continue) + } + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt index 467cba0f69..74507aa1d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt @@ -91,7 +91,7 @@ class ToolModMenu( } override fun handleAddItem(slot: Int, item: ItemStack, event: InventoryInteractEvent) { - if (!canAdd(item, event.whoClicked as Player)) { + if (!canAdd(item, slot, event.whoClicked as Player)) { event.isCancelled = true return } @@ -105,7 +105,7 @@ class ToolModMenu( } override fun handleSwapItem(slot: Int, currentItem: ItemStack, new: ItemStack, event: InventoryClickEvent) { - if (!canAdd(new, event.playerClicker)) { + if (!canAdd(new, slot, event.playerClicker)) { event.isCancelled = true return } @@ -116,7 +116,7 @@ class ToolModMenu( rebuildFromContents(modified) } - private fun canAdd(itemStack: ItemStack, player: Player): Boolean { + override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { val customItem = itemStack.customItem if (customItem !is ModificationItem) { return false @@ -151,13 +151,19 @@ class ToolModMenu( } } + // No locked slots + override fun canRemove(slot: Int, player: Player): Boolean { + return true + } + + override fun itemChanged(changedSlot: Int, changedItem: ItemStack) {} + companion object : SLEventListener() { fun create(viewer: Player, itemStack: ItemStack, customItem: CustomItem, manager: ModManager): ToolModMenu { val holder = ToolModMenu(viewer, itemStack, customItem, manager) setInventory(viewer.uniqueId, holder) return holder - } @EventHandler From 347f1ac015d4451032e969aa4015bb2b3589d7d3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Nov 2024 13:04:08 -0600 Subject: [PATCH 301/500] Set second line to multiblock --- .../custom/blocks/MultiblockWorkbench.kt | 38 +++++++++++-------- .../ion/server/features/gui/GuiText.kt | 6 ++- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 549640f555..0059a8dc99 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.custom.blocks -import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItems @@ -8,11 +7,13 @@ import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiText import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.Block @@ -54,21 +55,12 @@ object MultiblockWorkbench : InteractableCustomBlock( override val internalInventory: Inventory = IonServer.server.createInventory(this, inventorySize) override fun setup(view: InventoryView) { - val text = GuiText("Multiblock Workbench") - text.add(text("Missing Materials! [Hover]", NamedTextColor.RED), line = 0) - text.setSlotOverlay( - "# # # # # # # # #", - "# # # . . . . . .", - "# . # . . . . . .", - "# # # . . . . . ." - ) - addGuiButton(18, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { it.setCustomModelData(GuiItem.LEFT.customModelData) it.displayName(text("Previous Multiblock").itemName) }) { multiblockIndex = (multiblockIndex - 1).coerceAtLeast(0) - updateMultiblock() + updateMultiblock(it.view) } addGuiButton(20, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { @@ -76,17 +68,31 @@ object MultiblockWorkbench : InteractableCustomBlock( it.displayName(text("Next Multiblock").itemName) }) { multiblockIndex = (multiblockIndex + 1).coerceAtMost(multiblocks.lastIndex) - updateMultiblock() + updateMultiblock(it.view) } noDropSlots.add(19) - view.setTitle(text.build()) + view.setTitle(getGuiText(empty())) + } + + private fun getGuiText(secondLine: Component): Component = GuiText("Multiblock Workbench") + .setSlotOverlay( + "# # # # # # # # #", + "# # # . . . . . .", + "# . # . . . . . .", + "# # # . . . . . ." + ) + .add(secondLine, line = 0) + .build() + + private fun setSecondLine(view: InventoryView, secondLine: Component) { + view.setTitle(getGuiText(secondLine)) } - private fun updateMultiblock() { + private fun updateMultiblock(view: InventoryView) { val atIndex = multiblocks[multiblockIndex] - viewer.information(atIndex.toString()) + setSecondLine(view, atIndex.getDisplayName()) } private fun isLockedSlot(slot: Int): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiText.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiText.kt index 77e5d7f669..a90e23216e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiText.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiText.kt @@ -73,7 +73,7 @@ class GuiText( verticalShift: Int = 0 ): GuiText { add(GuiComponent(component, line, alignment, horizontalShift, verticalShift)) - return this + return this } /** @@ -122,13 +122,15 @@ class GuiText( * '#' - fully covered slot * @param structureData list of strings indicating what each slot should be covered with */ - fun setSlotOverlay(vararg structureData: String) { + fun setSlotOverlay(vararg structureData: String): GuiText { slotOverlayStructure.clear() for (row in structureData) { val sanitizedRow = row.replace(" ", "").replace("\n", "") slotOverlayStructure.add(sanitizedRow) } + + return this } /** From dc6f34033b41fa3f1068db7260d1df87b414286f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 15 Nov 2024 14:06:31 -0600 Subject: [PATCH 302/500] Check item requirements --- .../custom/blocks/MultiblockWorkbench.kt | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 0059a8dc99..2eba395d45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.custom.blocks +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItems @@ -7,6 +8,7 @@ import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiText import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration +import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.text.itemName @@ -14,6 +16,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.RED import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.Block @@ -35,8 +38,10 @@ object MultiblockWorkbench : InteractableCustomBlock( ) ) { private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) - private var multiblockIndex = 0 + val multiblocks = MultiblockRegistration.getAllMultiblocks().toList() + private var multiblockIndex = 0 + private val currentMultiblock get() = multiblocks[multiblockIndex] override fun onRightClick(event: PlayerInteractEvent, block: Block) { val player = event.player @@ -71,7 +76,12 @@ object MultiblockWorkbench : InteractableCustomBlock( updateMultiblock(it.view) } - noDropSlots.add(19) + addGuiButton(28, ItemStack(Material.BARRIER).updateMeta { + it.setCustomModelData(GuiItem.RIGHT.customModelData) + it.displayName(text("Missing Materials!", RED).itemName) + }) { + updateMultiblock(it.view) + } view.setTitle(getGuiText(empty())) } @@ -91,8 +101,51 @@ object MultiblockWorkbench : InteractableCustomBlock( } private fun updateMultiblock(view: InventoryView) { - val atIndex = multiblocks[multiblockIndex] - setSecondLine(view, atIndex.getDisplayName()) + setSecondLine(view, currentMultiblock.getDisplayName()) + updateConfirmationButton() + } + + private val editSlots = setOf(12..17, 21..26, 30..35).flatten() + + private fun checkRequirements(): List { + val items = internalInventory.contents.withIndex().filter { editSlots.contains(it.index) }.mapNotNull { it.value } + return consumeItems(items.mapTo(mutableListOf()) { it.clone() }) + } + + private fun consumeItems(items: MutableList): List { + val itemRequirements = currentMultiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } + val missing = mutableListOf() + + for (blockRequirement in itemRequirements) { + val requirement = blockRequirement.itemRequirement + if (items.any { requirement.itemCheck(it) && requirement.consumeItem(it) }) continue + missing.add(blockRequirement) + } + + return missing + } + + private fun updateConfirmationButton() { + val item = inventory.contents[28] ?: return + val missing = checkRequirements() + + if (missing.isNotEmpty()) { + item.type = Material.BARRIER + + val missingNames = missing.groupBy { it.alias }.map { text("${it.key.replaceFirstChar { char -> char.uppercase() }}: ${it.value.size}").itemName } + + item.updateMeta { + it.displayName(text("Missing Materials!", RED).itemName) + it.lore(missingNames) + } + return + } + + item.type = Material.WARPED_FUNGUS_ON_A_STICK + item.updateMeta { + it.displayName(ofChildren(text("Package "), currentMultiblock.getDisplayName()).itemName) + it.setCustomModelData(GuiItem.UP.customModelData) + } } private fun isLockedSlot(slot: Int): Boolean { @@ -105,7 +158,9 @@ object MultiblockWorkbench : InteractableCustomBlock( return internalInventory } - override fun itemChanged(changedSlot: Int, changedItem: ItemStack) {} + override fun itemChanged(changedSlot: Int, changedItem: ItemStack) { + updateConfirmationButton() + } override fun canRemove(slot: Int, player: Player): Boolean { return !isLockedSlot(slot) From eb20532f31c05f8359430a27d1a82d0b3be374fd Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Nov 2024 10:38:37 -0600 Subject: [PATCH 303/500] half of item requirenments --- .../custom/items/misc/MultiblockToken.kt | 10 ++--- .../custom/items/misc/MultimeterItem.kt | 2 +- .../custom/items/misc/PackagedMultiblock.kt | 20 ++++++++++ .../server/features/multiblock/PrePackaged.kt | 40 +++++-------------- 4 files changed, 35 insertions(+), 37 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index a905c38a1f..bbf49257ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged -import net.horizonsend.ion.server.features.multiblock.PrePackaged.getPackagedData +import net.horizonsend.ion.server.features.multiblock.PrePackaged.getTokenData import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.text.itemName @@ -36,7 +36,7 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { val base = constructItemStack() return base.updateMeta { - PrePackaged.packageData(PrePackaged.PackagedMultiblockData(multiblock), it.persistentDataContainer) + PrePackaged.setTokenData(multiblock, it.persistentDataContainer) it.displayName(ofChildren(multiblock.getDisplayName(), text(" Token")).itemName) it.lore(listOf( text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", GRAY).itemName, @@ -48,7 +48,7 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { if (itemStack.type.isAir) return - val packagedData = getPackagedData(itemStack) ?: run { + val packagedData = getTokenData(itemStack) ?: run { livingEntity.userError("The packaged multiblock has no data!") return } @@ -60,10 +60,10 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { val origin = PrePackaged.getOriginFromPlacement( event.clickedBlock ?: return, livingEntity.facing, - packagedData.multiblock.shape + packagedData.shape ) - val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.multiblock.shape) + val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.shape) if (obstructions.isNotEmpty()) { livingEntity.userError("Placement is obstructed!") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 48fcd93fc0..f929533c37 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -41,7 +41,7 @@ import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG import java.util.PriorityQueue -object MultimeterItem : CustomItem("Multimeter") { +object MultimeterItem : CustomItem("MULTIMETER") { override fun constructItemStack(): ItemStack { return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { it.displayName(Component.text("Multimeter", NamedTextColor.YELLOW).decoration(TextDecoration.ITALIC, false)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt new file mode 100644 index 0000000000..d017892961 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.custom.items.misc + +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import org.bukkit.Material +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType.STRING + +object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { + override fun constructItemStack(): ItemStack { + return ItemStack(Material.CHEST).updateMeta { + it.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) + } + } + + fun createFor() { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 9af6a5c774..838c6e061a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -1,9 +1,6 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.server.features.custom.items.CustomBlockItem -import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem -import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -59,8 +56,8 @@ object PrePackaged { return obstructed } - fun place(player: Player, origin: Block, direction: BlockFace, data: PackagedMultiblockData) { - val requirements = data.multiblock.shape.getRequirementMap(direction) + fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock) { + val requirements = multiblock.shape.getRequirementMap(direction) val placements = mutableMapOf() for ((offset, requirement) in requirements) { @@ -90,7 +87,7 @@ object PrePackaged { origin.world.playSound(block.location, soundGroup.placeSound, soundGroup.volume, soundGroup.pitch) } - if (data.multiblock is SignlessStarshipWeaponMultiblock<*>) return + if (multiblock is SignlessStarshipWeaponMultiblock<*>) return // Add sign val signPosition = origin.getRelative(direction.oppositeFace, 1) @@ -103,45 +100,26 @@ object PrePackaged { val sign = signPosition.state as Sign // Set the detection name just in case the setup fails - sign.getSide(Side.FRONT).line(0, text("[${data.multiblock.name}]")) + sign.getSide(Side.FRONT).line(0, text("[${multiblock.name}]")) sign.update() MultiblockAccess.tryDetectMultiblock(player, sign, direction, false) - data.multiblock.setupSign(player, sign) + multiblock.setupSign(player, sign) } - data class PackagedMultiblockData( - val multiblock: Multiblock - ) - - fun getPackagedData(itemStack: ItemStack): PackagedMultiblockData? { + fun getTokenData(itemStack: ItemStack): Multiblock? { val data = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER) ?: return null - //TODO rework for player packaged items val storageName = data.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING)!! - val multiblock = MultiblockRegistration.getByStorageName(storageName)!! - - return PackagedMultiblockData(multiblock) + return MultiblockRegistration.getByStorageName(storageName)!! } - fun packageData(data: PackagedMultiblockData, destination: PersistentDataContainer) { + fun setTokenData(multiblock: Multiblock, destination: PersistentDataContainer) { val pdc = destination.adapterContext.newPersistentDataContainer() - pdc.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, data.multiblock.javaClass.simpleName) + pdc.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, multiblock.javaClass.simpleName) destination.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) } - fun itemMatchesRequirement(itemStack: ItemStack, requirement: BlockRequirement): Boolean { - val customBlock = itemStack.customItem as? CustomBlockItem - - if (customBlock != null) { - return requirement.checkBlockData(customBlock.getCustomBlock().blockData) - } - - val type = itemStack.type - if (!type.isBlock) return false - //TODO something with double slabs - return requirement.checkBlockData(type.createBlockData()) - } } From 7904345eee772c8a83570206008c8c03d73753af Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Nov 2024 12:50:11 -0600 Subject: [PATCH 304/500] improve item consumption, packaging --- .../custom/blocks/MultiblockWorkbench.kt | 107 ++++++++++++------ .../custom/items/misc/MultiblockToken.kt | 2 +- .../custom/items/misc/PackagedMultiblock.kt | 63 ++++++++++- .../server/features/multiblock/PrePackaged.kt | 14 ++- .../multiblock/shape/BlockRequirement.kt | 9 +- .../multiblock/shape/MultiblockShape.kt | 18 +-- 6 files changed, 161 insertions(+), 52 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 2eba395d45..020d706d33 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,32 +1,36 @@ package net.horizonsend.ion.server.features.custom.blocks -import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiText import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.BlockFace +import org.bukkit.block.Chest import org.bukkit.entity.Player import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.BlockStateMeta import java.util.concurrent.TimeUnit object MultiblockWorkbench : InteractableCustomBlock( @@ -80,10 +84,15 @@ object MultiblockWorkbench : InteractableCustomBlock( it.setCustomModelData(GuiItem.RIGHT.customModelData) it.displayName(text("Missing Materials!", RED).itemName) }) { - updateMultiblock(it.view) + tryPack() + updateConfirmationButton() } - view.setTitle(getGuiText(empty())) + lockedSlots.addAll(setOf(0..11, 27..29).flatten()) + lockedSlots.add(18) + lockedSlots.add(20) + + view.setTitle(getGuiText(currentMultiblock.getDisplayName())) } private fun getGuiText(secondLine: Component): Component = GuiText("Multiblock Workbench") @@ -107,68 +116,102 @@ object MultiblockWorkbench : InteractableCustomBlock( private val editSlots = setOf(12..17, 21..26, 30..35).flatten() - private fun checkRequirements(): List { - val items = internalInventory.contents.withIndex().filter { editSlots.contains(it.index) }.mapNotNull { it.value } - return consumeItems(items.mapTo(mutableListOf()) { it.clone() }) + private fun getConsumableItems(): List { + return internalInventory.contents.withIndex() + .filter { editSlots.contains(it.index) } + .mapNotNull { it.value } } - private fun consumeItems(items: MutableList): List { + private fun checkRequirements(): List { + val items = getConsumableItems().mapTo(mutableListOf()) { it.clone() } + val itemRequirements = currentMultiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } val missing = mutableListOf() for (blockRequirement in itemRequirements) { val requirement = blockRequirement.itemRequirement - if (items.any { requirement.itemCheck(it) && requirement.consumeItem(it) }) continue + if (items.any { requirement.itemCheck(it) && requirement.consume(it) }) continue missing.add(blockRequirement) } return missing } - private fun updateConfirmationButton() { - val item = inventory.contents[28] ?: return + fun packageTo(destination: Inventory) { + val items = getConsumableItems() + val itemRequirements = currentMultiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } + val missing = mutableListOf() + + for (blockRequirement in itemRequirements) { + val requirement = blockRequirement.itemRequirement + val success = items.firstOrNull { requirement.itemCheck(it) && requirement.consume(it) } + + if (success == null) { + missing.add(blockRequirement) + continue + } + + val amount = requirement.amountConsumed(success) + LegacyItemUtils.addToInventory(destination, success.asQuantity(amount)) + } + } + + private fun createPackagedItem(): ItemStack { + val base = PackagedMultiblock.createFor(currentMultiblock) + return base.updateMeta { + it as BlockStateMeta + + val newState = Material.CHEST.createBlockData().createBlockState() as Chest + packageTo(newState.inventory) + + it.blockState = newState + } + } + + private var ready: Boolean = false + + private fun updateConfirmationButton() = Tasks.sync { + val item = inventory.contents[28] ?: return@sync val missing = checkRequirements() if (missing.isNotEmpty()) { item.type = Material.BARRIER - - val missingNames = missing.groupBy { it.alias }.map { text("${it.key.replaceFirstChar { char -> char.uppercase() }}: ${it.value.size}").itemName } - item.updateMeta { it.displayName(text("Missing Materials!", RED).itemName) - it.lore(missingNames) + it.lore(missing.groupBy { it.alias }.map { text("${it.key.replaceFirstChar { char -> char.uppercase() }}: ${it.value.size}").itemName }) } - return + + ready = false + return@sync } item.type = Material.WARPED_FUNGUS_ON_A_STICK item.updateMeta { - it.displayName(ofChildren(text("Package "), currentMultiblock.getDisplayName()).itemName) - it.setCustomModelData(GuiItem.UP.customModelData) + it.lore(listOf()) + it.displayName(text("Packaged multiblock ready!", GREEN).itemName) + it.setCustomModelData(114) } - } - private fun isLockedSlot(slot: Int): Boolean { - if (slot in 0..11) return true - if (slot in 18..20) return true - return slot in 27..29 + ready = true } - override fun getInventory(): Inventory { - return internalInventory - } + private fun tryPack() { + if (!ready) return + val packagedItem = createPackagedItem() + + if (internalInventory.getItem(19)?.isSimilar(packagedItem) == true) { internalInventory.getItem(19)?.let { it.amount++ } } else { + internalInventory.setItem(19, packagedItem) + } - override fun itemChanged(changedSlot: Int, changedItem: ItemStack) { updateConfirmationButton() } - override fun canRemove(slot: Int, player: Player): Boolean { - return !isLockedSlot(slot) + override fun itemChanged(changedSlot: Int, changedItem: ItemStack) { + updateConfirmationButton() } - override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { - return !isLockedSlot(slot) - } + override fun canRemove(slot: Int, player: Player): Boolean { return true } + override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { return true } override fun handleClose(event: InventoryCloseEvent) { for ((slot, content) in inventory.contents.withIndex()) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index bbf49257ce..92172c831b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -71,7 +71,7 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { return } - runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData) } + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, null) } itemStack.amount-- } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index d017892961..d3de7343c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -1,11 +1,27 @@ package net.horizonsend.ion.server.features.custom.items.misc +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.PrePackaged +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Material +import org.bukkit.block.Chest +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.BlockStateMeta import org.bukkit.persistence.PersistentDataType.STRING +import java.util.Locale object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { override fun constructItemStack(): ItemStack { @@ -14,7 +30,50 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { } } - fun createFor() { - + fun createFor(multiblock: Multiblock): ItemStack { + return constructItemStack().updateMeta { + PrePackaged.setTokenData(multiblock, it.persistentDataContainer) + it.displayName(ofChildren(Component.text("Packaged "), multiblock.getDisplayName()).itemName) + it.lore(listOf( + Component.text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", NamedTextColor.GRAY).itemName, + Component.text("Variant: ${multiblock.javaClass.simpleName}", NamedTextColor.GRAY).itemName + )) + } + } + + override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + if (itemStack.type.isAir) return + + val packagedData = PrePackaged.getTokenData(itemStack) ?: run { + livingEntity.userError("The packaged multiblock has no data!") + return + } + + val inventory = ((itemStack.itemMeta as? BlockStateMeta)?.blockState as? Chest)?.inventory ?: return livingEntity.userError("The packaged multiblock has no data!") + + if (livingEntity !is Player) return + + if (event == null) return + + val origin = PrePackaged.getOriginFromPlacement( + event.clickedBlock ?: return, + livingEntity.facing, + packagedData.shape + ) + + val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.shape) + + if (obstructions.isNotEmpty()) { + livingEntity.userError("Placement is obstructed!") + livingEntity.highlightBlocks(obstructions, 50L) + return + } + + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, inventory) }.onFailure { + livingEntity.information("ERROR: $it") + it.printStackTrace() + } + + itemStack.amount-- } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 838c6e061a..6c734a696d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -17,6 +17,7 @@ import org.bukkit.block.sign.Side import org.bukkit.entity.Player import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.EquipmentSlot +import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -56,7 +57,7 @@ object PrePackaged { return obstructed } - fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock) { + fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock, itemSource: Inventory?) { val requirements = multiblock.shape.getRequirementMap(direction) val placements = mutableMapOf() @@ -64,6 +65,15 @@ object PrePackaged { val absolute = Vec3i(origin.x, origin.y, origin.z) + offset val (x, y, z) = absolute + if (itemSource != null) { + itemSource + .filterNotNull() + .firstOrNull { requirement.itemRequirement.itemCheck(it) } + ?.let { + requirement.itemRequirement.consume(it) + } + } + val existingBlock = origin.world.getBlockAt(x, y, z) val event = BlockPlaceEvent( @@ -120,6 +130,4 @@ object PrePackaged { destination.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) } - - } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index e88983f73c..c52a79af70 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -31,6 +31,11 @@ class BlockRequirement( class ItemRequirement( val itemCheck: (ItemStack) -> Boolean, - val consumeItem: (ItemStack) -> Boolean - ) + val amountConsumed: (ItemStack) -> Int + ) { + fun consume(itemStack: ItemStack): Boolean { + itemStack.amount -= amountConsumed(itemStack) + return itemStack.amount >= 0 + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 67afb0e8e4..835bd77207 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -235,7 +235,7 @@ class MultiblockShape { dataCheck = { type == it.material }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { type == it.type }, - consumeItem = { it.amount-- >= 0 } + amountConsumed = { 1 } ) ) @@ -254,7 +254,7 @@ class MultiblockShape { dataCheck = { typeSet.contains(it.material) }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { typeSet.contains(it.type) }, - consumeItem = { it.amount-- >= 0 } + amountConsumed = { 1 } ) ) @@ -275,7 +275,7 @@ class MultiblockShape { dataCheck = { CustomBlocks.getByBlockData(it) == customBlock }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { val customItem = it.customItem; customItem is CustomBlockItem && customItem.getCustomBlock() == customBlock }, - consumeItem = { it.amount-- >= 0 } + amountConsumed = { 1 } ) ) @@ -336,10 +336,7 @@ class MultiblockShape { dataCheck = { it is Slab && it.type == DOUBLE }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) }, - consumeItem = { - it.amount -= 2 - it.amount >= 0 - } + amountConsumed = { 2 } ), ) ) @@ -359,10 +356,7 @@ class MultiblockShape { dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) || it.type.isTerracotta }, - consumeItem = { - if (it.type.isSlab) it.amount -= 2 else it.amount-- - it.amount >= 0 - } + amountConsumed = { if (it.type.isSlab) 2 else 1 } ), ) } @@ -500,7 +494,7 @@ class MultiblockShape { dataCheck = { it is Furnace }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { it.type == Material.FURNACE }, - consumeItem = { it.amount-- >= 0 } + amountConsumed = { 1 } ) )) From 105d2c57318626557a0e1ba32ade2079831c6705 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Nov 2024 13:14:44 -0600 Subject: [PATCH 305/500] cleanup --- .../custom/blocks/MultiblockWorkbench.kt | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 020d706d33..aa0094648f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -15,7 +15,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta -import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED @@ -92,25 +91,25 @@ object MultiblockWorkbench : InteractableCustomBlock( lockedSlots.add(18) lockedSlots.add(20) - view.setTitle(getGuiText(currentMultiblock.getDisplayName())) + setGuiOverlay(view) } - private fun getGuiText(secondLine: Component): Component = GuiText("Multiblock Workbench") - .setSlotOverlay( - "# # # # # # # # #", - "# # # . . . . . .", - "# . # . . . . . .", - "# # # . . . . . ." - ) - .add(secondLine, line = 0) - .build() - - private fun setSecondLine(view: InventoryView, secondLine: Component) { - view.setTitle(getGuiText(secondLine)) + private fun setGuiOverlay(view: InventoryView) { + val text = GuiText("Multiblock Workbench") + .setSlotOverlay( + "# # # # # # # # #", + "# # # . . . . . .", + "# . # . . . . . .", + "# # # . . . . . ." + ) + .add(currentMultiblock.getDisplayName(), line = 0) + .build() + + view.setTitle(text) } private fun updateMultiblock(view: InventoryView) { - setSecondLine(view, currentMultiblock.getDisplayName()) + setGuiOverlay(view) updateConfirmationButton() } @@ -137,7 +136,7 @@ object MultiblockWorkbench : InteractableCustomBlock( return missing } - fun packageTo(destination: Inventory) { + private fun packageTo(destination: Inventory) { val items = getConsumableItems() val itemRequirements = currentMultiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } val missing = mutableListOf() @@ -161,6 +160,7 @@ object MultiblockWorkbench : InteractableCustomBlock( return base.updateMeta { it as BlockStateMeta + @Suppress("UnstableApiUsage") val newState = Material.CHEST.createBlockData().createBlockState() as Chest packageTo(newState.inventory) From 8696cba7c6d868973379a09b85b8cc178dee645c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Nov 2024 14:05:42 -0600 Subject: [PATCH 306/500] Remove magic numbers, more cleanup, some comments --- .../custom/blocks/MultiblockWorkbench.kt | 140 ++++++------------ .../server/features/multiblock/PrePackaged.kt | 56 +++++++ 2 files changed, 104 insertions(+), 92 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index aa0094648f..d77455eb63 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -3,14 +3,13 @@ package net.horizonsend.ion.server.features.custom.blocks import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItems -import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiText import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration -import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement +import net.horizonsend.ion.server.features.multiblock.PrePackaged.checkRequirements +import net.horizonsend.ion.server.features.multiblock.PrePackaged.createPackagedItem import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName -import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.text.itemName @@ -18,18 +17,17 @@ import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED +import net.kyori.adventure.text.format.NamedTextColor.WHITE import org.bukkit.Location import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.BlockFace -import org.bukkit.block.Chest import org.bukkit.entity.Player import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.BlockStateMeta import java.util.concurrent.TimeUnit object MultiblockWorkbench : InteractableCustomBlock( @@ -62,36 +60,42 @@ object MultiblockWorkbench : InteractableCustomBlock( override val inventorySize = 36 override val internalInventory: Inventory = IonServer.server.createInventory(this, inventorySize) + private companion object { + const val LEFT_BUTTON_SLOT = 18 + const val RESULT_SLOT = 19 + const val RIGHT_BUTTON_SLOT = 20 + const val CONFIRM_BUTTON_SLOT = 28 + + val BACKGROUND_SLOTS = setOf(0..11, 27..29).flatten() + val INVENTORY_SLOTS = setOf(12..17, 21..26, 30..35).flatten() + } + override fun setup(view: InventoryView) { - addGuiButton(18, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + lockedSlots.addAll(BACKGROUND_SLOTS) + setGuiOverlay(view) + + addGuiButton(LEFT_BUTTON_SLOT, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { it.setCustomModelData(GuiItem.LEFT.customModelData) it.displayName(text("Previous Multiblock").itemName) }) { multiblockIndex = (multiblockIndex - 1).coerceAtLeast(0) - updateMultiblock(it.view) + refreshMultiblock(it.view) } - addGuiButton(20, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + addGuiButton(RIGHT_BUTTON_SLOT, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { it.setCustomModelData(GuiItem.RIGHT.customModelData) it.displayName(text("Next Multiblock").itemName) }) { multiblockIndex = (multiblockIndex + 1).coerceAtMost(multiblocks.lastIndex) - updateMultiblock(it.view) + refreshMultiblock(it.view) } - addGuiButton(28, ItemStack(Material.BARRIER).updateMeta { - it.setCustomModelData(GuiItem.RIGHT.customModelData) - it.displayName(text("Missing Materials!", RED).itemName) - }) { + addGuiButton(CONFIRM_BUTTON_SLOT, ItemStack(Material.BARRIER)) { tryPack() updateConfirmationButton() } - - lockedSlots.addAll(setOf(0..11, 27..29).flatten()) - lockedSlots.add(18) - lockedSlots.add(20) - - setGuiOverlay(view) + // Perform full setup of the button + updateConfirmationButton() } private fun setGuiOverlay(view: InventoryView) { @@ -108,77 +112,30 @@ object MultiblockWorkbench : InteractableCustomBlock( view.setTitle(text) } - private fun updateMultiblock(view: InventoryView) { + private fun refreshMultiblock(view: InventoryView) { setGuiOverlay(view) updateConfirmationButton() } - private val editSlots = setOf(12..17, 21..26, 30..35).flatten() - - private fun getConsumableItems(): List { - return internalInventory.contents.withIndex() - .filter { editSlots.contains(it.index) } - .mapNotNull { it.value } - } - - private fun checkRequirements(): List { - val items = getConsumableItems().mapTo(mutableListOf()) { it.clone() } - - val itemRequirements = currentMultiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } - val missing = mutableListOf() - - for (blockRequirement in itemRequirements) { - val requirement = blockRequirement.itemRequirement - if (items.any { requirement.itemCheck(it) && requirement.consume(it) }) continue - missing.add(blockRequirement) - } - - return missing - } - - private fun packageTo(destination: Inventory) { - val items = getConsumableItems() - val itemRequirements = currentMultiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } - val missing = mutableListOf() - - for (blockRequirement in itemRequirements) { - val requirement = blockRequirement.itemRequirement - val success = items.firstOrNull { requirement.itemCheck(it) && requirement.consume(it) } - - if (success == null) { - missing.add(blockRequirement) - continue - } - - val amount = requirement.amountConsumed(success) - LegacyItemUtils.addToInventory(destination, success.asQuantity(amount)) - } - } - - private fun createPackagedItem(): ItemStack { - val base = PackagedMultiblock.createFor(currentMultiblock) - return base.updateMeta { - it as BlockStateMeta - - @Suppress("UnstableApiUsage") - val newState = Material.CHEST.createBlockData().createBlockState() as Chest - packageTo(newState.inventory) - - it.blockState = newState - } - } - private var ready: Boolean = false + /** + * Update the confirmation button to indicate whether the item requirements are fulfilled + **/ private fun updateConfirmationButton() = Tasks.sync { - val item = inventory.contents[28] ?: return@sync - val missing = checkRequirements() + val item = inventory.contents[CONFIRM_BUTTON_SLOT] ?: return@sync + val missing = checkRequirements(getUnlockedItems(), currentMultiblock) if (missing.isNotEmpty()) { item.type = Material.BARRIER + val missingLore = missing + .groupBy { it.alias } + // Group by the same alias, count the number needed of that alias. Get a result like "Any slab: 3" + .map { (description , entries) -> text("${description.replaceFirstChar { char -> char.uppercase() }}: ${entries.size}", WHITE).itemName } + item.updateMeta { it.displayName(text("Missing Materials!", RED).itemName) - it.lore(missing.groupBy { it.alias }.map { text("${it.key.replaceFirstChar { char -> char.uppercase() }}: ${it.value.size}").itemName }) + it.lore(missingLore) } ready = false @@ -195,29 +152,28 @@ object MultiblockWorkbench : InteractableCustomBlock( ready = true } + private fun tryPack() { if (!ready) return - val packagedItem = createPackagedItem() + if (checkRequirements(getUnlockedItems(), currentMultiblock).isNotEmpty()) return // Just double check I don't want a dupe from a stuck ready state + val packagedItem = createPackagedItem(getUnlockedItems(), currentMultiblock) - if (internalInventory.getItem(19)?.isSimilar(packagedItem) == true) { internalInventory.getItem(19)?.let { it.amount++ } } else { - internalInventory.setItem(19, packagedItem) - } + // Increment or set the item + val currentItem = internalInventory.getItem(RESULT_SLOT) - updateConfirmationButton() - } + if (currentItem == null) { + internalInventory.setItem(RESULT_SLOT, packagedItem) + } else { + currentItem.amount++ + } - override fun itemChanged(changedSlot: Int, changedItem: ItemStack) { + // Update after items have been consumed updateConfirmationButton() } + override fun itemChanged(changedSlot: Int, changedItem: ItemStack) = updateConfirmationButton() override fun canRemove(slot: Int, player: Player): Boolean { return true } override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { return true } - - override fun handleClose(event: InventoryCloseEvent) { - for ((slot, content) in inventory.contents.withIndex()) { - if (noDropSlots.contains(slot)) continue - viewer.world.dropItemNaturally(location, content ?: continue) - } - } + override fun handleClose(event: InventoryCloseEvent) = dropItems(location) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 6c734a696d..16ff81e315 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -1,15 +1,20 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.BlockFace +import org.bukkit.block.Chest import org.bukkit.block.Sign import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional @@ -19,6 +24,7 @@ import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.EquipmentSlot import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.BlockStateMeta import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -130,4 +136,54 @@ object PrePackaged { destination.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) } + + /** Moves the needed materials for the provided multiblock from the list of items to the destination inventory */ + fun packageFrom(items: List, multiblock: Multiblock, destination: Inventory) { + val itemRequirements = multiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } + val missing = mutableListOf() + + for (blockRequirement in itemRequirements) { + val requirement = blockRequirement.itemRequirement + val success = items.firstOrNull { requirement.itemCheck(it) && requirement.consume(it) } + + if (success == null) { + missing.add(blockRequirement) + continue + } + + val amount = requirement.amountConsumed(success) + LegacyItemUtils.addToInventory(destination, success.asQuantity(amount)) + } + } + + fun createPackagedItem(availableItems: List, multiblock: Multiblock): ItemStack { + val base = PackagedMultiblock.createFor(multiblock) + return base.updateMeta { + it as BlockStateMeta + + @Suppress("UnstableApiUsage") + val newState = Material.CHEST.createBlockData().createBlockState() as Chest + packageFrom(availableItems, multiblock, newState.inventory) + + it.blockState = newState + } + } + + /** + * Returns a list of requirements not met by the existing items + **/ + fun checkRequirements(available: Iterable, multiblock: Multiblock): List { + val items = available.mapTo(mutableListOf()) { it.clone() } + + val itemRequirements = multiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } + val missing = mutableListOf() + + for (blockRequirement in itemRequirements) { + val requirement = blockRequirement.itemRequirement + if (items.any { requirement.itemCheck(it) && requirement.consume(it) }) continue + missing.add(blockRequirement) + } + + return missing + } } From 9dce55fe7ede4251a4aeb1656ac2419868e9170e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Nov 2024 14:15:42 -0600 Subject: [PATCH 307/500] Remember what block was used --- .../server/features/multiblock/PrePackaged.kt | 11 +++++++- .../multiblock/shape/BlockRequirement.kt | 3 +- .../multiblock/shape/MultiblockShape.kt | 28 +++++++++++++++---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 16ff81e315..d6df1cfb5d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -71,11 +71,14 @@ object PrePackaged { val absolute = Vec3i(origin.x, origin.y, origin.z) + offset val (x, y, z) = absolute + var usedItem: ItemStack? = null + if (itemSource != null) { itemSource .filterNotNull() .firstOrNull { requirement.itemRequirement.itemCheck(it) } ?.let { + usedItem = it.clone() requirement.itemRequirement.consume(it) } } @@ -94,7 +97,13 @@ object PrePackaged { if (!event) return player.userError("You can't build here!") - placements[existingBlock] = requirement.example.invoke(direction) + val placement = if (usedItem == null) { + requirement.example.invoke(direction) + } else { + requirement.itemRequirement.toBlock.invoke(usedItem!!, direction) + } + + placements[existingBlock] = placement } for ((block, placement) in placements) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index c52a79af70..d9613517a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -31,7 +31,8 @@ class BlockRequirement( class ItemRequirement( val itemCheck: (ItemStack) -> Boolean, - val amountConsumed: (ItemStack) -> Int + val amountConsumed: (ItemStack) -> Int, + val toBlock: (ItemStack, BlockFace) -> BlockData ) { fun consume(itemStack: ItemStack): Boolean { itemStack.amount -= amountConsumed(itemStack) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 835bd77207..138f90f8e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -235,7 +235,8 @@ class MultiblockShape { dataCheck = { type == it.material }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { type == it.type }, - amountConsumed = { 1 } + amountConsumed = { 1 }, + toBlock = { item, _ -> item.type.createBlockData() } ) ) @@ -254,7 +255,8 @@ class MultiblockShape { dataCheck = { typeSet.contains(it.material) }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { typeSet.contains(it.type) }, - amountConsumed = { 1 } + amountConsumed = { 1 }, + toBlock = { item, _ -> item.type.createBlockData() } ) ) @@ -275,7 +277,8 @@ class MultiblockShape { dataCheck = { CustomBlocks.getByBlockData(it) == customBlock }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { val customItem = it.customItem; customItem is CustomBlockItem && customItem.getCustomBlock() == customBlock }, - amountConsumed = { 1 } + amountConsumed = { 1 }, + toBlock = { _, _ -> customBlock.blockData } ) ) @@ -336,7 +339,8 @@ class MultiblockShape { dataCheck = { it is Slab && it.type == DOUBLE }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) }, - amountConsumed = { 2 } + amountConsumed = { 2 }, + toBlock = { item, _ -> (item.type.createBlockData() as Slab).apply { this.type = DOUBLE } } ), ) ) @@ -356,7 +360,13 @@ class MultiblockShape { dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) || it.type.isTerracotta }, - amountConsumed = { if (it.type.isSlab) 2 else 1 } + amountConsumed = { if (it.type.isSlab) 2 else 1 }, + toBlock = { item, _ -> + val type = item.type + if (type.isSlab) { + (type.createBlockData() as Slab).apply { this.type = DOUBLE } + } else type.createBlockData() + } ), ) } @@ -494,7 +504,13 @@ class MultiblockShape { dataCheck = { it is Furnace }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { it.type == Material.FURNACE }, - amountConsumed = { 1 } + amountConsumed = { 1 }, + toBlock = { _, face -> + Material.FURNACE.createBlockData { + it as Furnace + it.facing = face.oppositeFace + } + } ) )) From eacf527f6402efad1ff143234fef1ec03638f929 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 16 Nov 2024 14:33:28 -0600 Subject: [PATCH 308/500] Move placement modifications to their own function --- .../server/command/misc/MultiblockCommand.kt | 9 ++-- .../server/features/multiblock/PrePackaged.kt | 6 ++- .../multiblock/shape/BlockRequirement.kt | 26 +++++++++-- .../multiblock/shape/MultiblockShape.kt | 44 +++++++------------ .../multiblock/util/PrepackagedPreset.kt | 24 +++++----- 5 files changed, 57 insertions(+), 52 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 7c0cc321c4..228407ad51 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -90,8 +90,6 @@ object MultiblockCommand : SLCommand() { val face = sign.getFacing().oppositeFace lastMatch.shape.getRequirementMap(face).forEach { (coords, requirement) -> - val expected = requirement.example - val requirementX = coords.x val requirementY = coords.y val requirementZ = coords.z @@ -106,7 +104,8 @@ object MultiblockCommand : SLCommand() { if (!requirementMet) { val (xx, yy, zz) = Vec3i(relative.location) - sendEntityPacket(sender, displayBlock(sender.world.minecraft, expected.invoke(face), Vector(xx, yy, zz), 0.5f, true), 10 * 20L) + + sendEntityPacket(sender, displayBlock(sender.world.minecraft, requirement.getExample(face), Vector(xx, yy, zz), 0.5f, true), 10 * 20L) sender.userError( "Block at ${Vec3i(relative.location)} doesn't match! Expected ${requirement.alias}, found ${relative.type}." ) @@ -127,8 +126,6 @@ object MultiblockCommand : SLCommand() { val (x, y, z) = absolute - val blockData = requirement.example - val existingBlock = sender.world.getBlockAt(x, y, z) val event = BlockPlaceEvent( @@ -143,7 +140,7 @@ object MultiblockCommand : SLCommand() { if (!event) return sender.userError("You can't build here!") - existingBlock.blockData = blockData.invoke(sender.facing) + existingBlock.blockData = requirement.getExample(sender.facing) } sender.success("Placed ${multiblock.javaClass.simpleName}") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index d6df1cfb5d..bc59e7a12e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -98,11 +98,13 @@ object PrePackaged { if (!event) return player.userError("You can't build here!") val placement = if (usedItem == null) { - requirement.example.invoke(direction) + requirement.example.clone() } else { - requirement.itemRequirement.toBlock.invoke(usedItem!!, direction) + requirement.itemRequirement.toBlock.invoke(usedItem!!) } + requirement.executePlacementModifications(placement, direction) + placements[existingBlock] = placement } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index d9613517a2..2405b577e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -8,31 +8,49 @@ import org.bukkit.inventory.ItemStack class BlockRequirement( val alias: String, - var example: (BlockFace) -> BlockData, + var example: BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, private val dataCheck: (BlockData) -> Boolean, val itemRequirement: ItemRequirement ) { + private val placementModifications: MutableList<(BlockFace, BlockData) -> Unit> = mutableListOf() + operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) fun checkBlockData(data: BlockData) = dataCheck.invoke(data) fun setExample(blockData: BlockData): BlockRequirement { - this.example = { blockData } + this.example = blockData return this } fun setExample(type: Material): BlockRequirement { - this.example = { type.createBlockData() } + this.example = type.createBlockData() + + return this + } + + fun addPlacementModification(modification: (BlockFace, BlockData) -> Unit): BlockRequirement { + placementModifications.add(modification) return this } + fun executePlacementModifications(data: BlockData, face: BlockFace) { + for (placementModification in placementModifications) { + placementModification.invoke(face, data) + } + } + + fun getExample(face: BlockFace): BlockData { + return example.clone().apply { executePlacementModifications(this, face) } + } + class ItemRequirement( val itemCheck: (ItemStack) -> Boolean, val amountConsumed: (ItemStack) -> Int, - val toBlock: (ItemStack, BlockFace) -> BlockData + val toBlock: (ItemStack) -> BlockData ) { fun consume(itemStack: ItemStack): Boolean { itemStack.amount -= amountConsumed(itemStack) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 138f90f8e2..7ffb1430d9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -230,13 +230,13 @@ class MultiblockShape { fun type(type: Material) { val requirement = BlockRequirement( alias = type.toString(), - example = { type.createBlockData() }, + example = type.createBlockData(), syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, dataCheck = { type == it.material }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { type == it.type }, amountConsumed = { 1 }, - toBlock = { item, _ -> item.type.createBlockData() } + toBlock = { item -> item.type.createBlockData() } ) ) @@ -248,7 +248,7 @@ class MultiblockShape { val requirement = BlockRequirement( alias = alias, - example = { types.first().createBlockData() }, + example = types.first().createBlockData(), syncCheck = { block, _, loadChunks -> typeSet.contains(if (loadChunks) block.type else block.getTypeSafe() ?: return@BlockRequirement false) }, @@ -256,7 +256,7 @@ class MultiblockShape { itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { typeSet.contains(it.type) }, amountConsumed = { 1 }, - toBlock = { item, _ -> item.type.createBlockData() } + toBlock = { item -> item.type.createBlockData() } ) ) @@ -268,7 +268,7 @@ class MultiblockShape { fun customBlock(customBlock: CustomBlock) { val requirement = BlockRequirement( alias = customBlock.identifier, - example = { customBlock.blockData }, + example = customBlock.blockData, syncCheck = { block, _, loadChunks -> if (loadChunks) CustomBlocks.getByBlock(block) else { getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } @@ -278,7 +278,7 @@ class MultiblockShape { itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { val customItem = it.customItem; customItem is CustomBlockItem && customItem.getCustomBlock() == customBlock }, amountConsumed = { 1 }, - toBlock = { _, _ -> customBlock.blockData } + toBlock = { _ -> customBlock.blockData } ) ) @@ -326,12 +326,7 @@ class MultiblockShape { fun anyDoubleSlab() = complete( BlockRequirement( alias = "any double slab block", - example = { - Material.STONE_BRICK_SLAB.createBlockData().apply { - this as Slab - this.type = DOUBLE - } - }, + example = (Material.STONE_BRICK_SLAB.createBlockData() as Slab).apply { this.type = DOUBLE }, syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) blockData is Slab && blockData.type == DOUBLE @@ -340,7 +335,7 @@ class MultiblockShape { itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) }, amountConsumed = { 2 }, - toBlock = { item, _ -> (item.type.createBlockData() as Slab).apply { this.type = DOUBLE } } + toBlock = { item -> (item.type.createBlockData() as Slab).apply { this.type = DOUBLE } } ), ) ) @@ -350,7 +345,7 @@ class MultiblockShape { fun terracottaOrDoubleslab() { BlockRequirement( alias = "any double slab or terracotta block", - example = { Material.CYAN_TERRACOTTA.createBlockData() }, + example = Material.CYAN_TERRACOTTA.createBlockData(), syncCheck = { block, _, loadChunks -> val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) val blockType = if (loadChunks) block.type else block.getTypeSafe() @@ -361,7 +356,7 @@ class MultiblockShape { itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) || it.type.isTerracotta }, amountConsumed = { if (it.type.isSlab) 2 else 1 }, - toBlock = { item, _ -> + toBlock = { item -> val type = item.type if (type.isSlab) { (type.createBlockData() as Slab).apply { this.type = DOUBLE } @@ -488,12 +483,7 @@ class MultiblockShape { fun machineFurnace() = complete(BlockRequirement( alias = "furnace", - example = { direction -> - Material.FURNACE.createBlockData { - it as Furnace - it.facing = direction.oppositeFace - } - }, + example = Material.FURNACE.createBlockData(), syncCheck = check@{ block, inward, loadChunks -> val blockData = if (loadChunks) block.getNMSBlockData() else getNMSBlockSateSafe(block.world, block.x, block.y, block.z) ?: return@check false @@ -505,14 +495,12 @@ class MultiblockShape { itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { it.type == Material.FURNACE }, amountConsumed = { 1 }, - toBlock = { _, face -> - Material.FURNACE.createBlockData { - it as Furnace - it.facing = face.oppositeFace - } - } + toBlock = { Material.FURNACE.createBlockData() } ) - )) + ).addPlacementModification { direction, data -> + data as Furnace + data.facing = direction.oppositeFace + }) fun solidBlock() = anyType( Material.STONE_BRICKS, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt index 7315e05832..322b310787 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt @@ -3,28 +3,28 @@ package net.horizonsend.ion.server.features.multiblock.util import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import org.bukkit.Material +import org.bukkit.block.BlockFace import org.bukkit.block.data.Bisected +import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.Fence import org.bukkit.block.data.type.Stairs object PrepackagedPreset { fun stairs(face: RelativeFace, half: Bisected.Half, shape: Stairs.Shape): BlockRequirement.() -> Unit = { - example = { multiblockDirection -> - Material.STONE_BRICK_STAIRS.createBlockData { stairs -> - stairs as Stairs - stairs.half = half - stairs.shape = shape - stairs.facing = face[multiblockDirection] - } + example = Material.STONE_BRICK_STAIRS.createBlockData() + addPlacementModification { multiblockDirection: BlockFace, stairs: BlockData -> + stairs as Stairs + stairs.half = half + stairs.shape = shape + stairs.facing = face[multiblockDirection] } } fun pane(vararg face: RelativeFace): BlockRequirement.() -> Unit = { - example = { multiblockDirection -> - Material.GLASS_PANE.createBlockData { pane -> - pane as Fence - face.forEach { pane.setFace(it[multiblockDirection], true) } - } + example = Material.GLASS_PANE.createBlockData() + addPlacementModification { multiblockDirection: BlockFace, pane: BlockData -> + pane as Fence + face.forEach { pane.setFace(it[multiblockDirection], true) } } } } From b07a0046eb3e2c2fc4cf52e209c567e58431c39b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 17 Nov 2024 18:52:21 -0600 Subject: [PATCH 309/500] Add search function --- .../custom/blocks/MultiblockWorkbench.kt | 70 ++++++++++++++++++- .../multiblock/MultiblockRegistration.kt | 2 +- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index d77455eb63..b4540fccb7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -5,16 +5,22 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItem import net.horizonsend.ion.server.features.custom.items.CustomItems import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiText +import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.TextInputMenu +import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.validator.ValidatorResult import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI +import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.PrePackaged.checkRequirements import net.horizonsend.ion.server.features.multiblock.PrePackaged.createPackagedItem import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.setDisplayNameAndGet import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED import net.kyori.adventure.text.format.NamedTextColor.WHITE @@ -61,6 +67,7 @@ object MultiblockWorkbench : InteractableCustomBlock( override val internalInventory: Inventory = IonServer.server.createInventory(this, inventorySize) private companion object { + const val SEARCH_BUTTON_SLOT = 10 const val LEFT_BUTTON_SLOT = 18 const val RESULT_SLOT = 19 const val RIGHT_BUTTON_SLOT = 20 @@ -90,12 +97,17 @@ object MultiblockWorkbench : InteractableCustomBlock( refreshMultiblock(it.view) } + addGuiButton(SEARCH_BUTTON_SLOT, ItemStack(Material.NAME_TAG).setDisplayNameAndGet(text("Search").itemName)) { + openSearchMenu(it.playerClicker) + } + addGuiButton(CONFIRM_BUTTON_SLOT, ItemStack(Material.BARRIER)) { tryPack() updateConfirmationButton() } // Perform full setup of the button updateConfirmationButton() + isSearching = false } private fun setGuiOverlay(view: InventoryView) { @@ -146,13 +158,12 @@ object MultiblockWorkbench : InteractableCustomBlock( item.updateMeta { it.lore(listOf()) it.displayName(text("Packaged multiblock ready!", GREEN).itemName) - it.setCustomModelData(114) + it.setCustomModelData(GuiItem.CHECKMARK.customModelData ) } ready = true } - private fun tryPack() { if (!ready) return if (checkRequirements(getUnlockedItems(), currentMultiblock).isNotEmpty()) return // Just double check I don't want a dupe from a stuck ready state @@ -174,6 +185,59 @@ object MultiblockWorkbench : InteractableCustomBlock( override fun itemChanged(changedSlot: Int, changedItem: ItemStack) = updateConfirmationButton() override fun canRemove(slot: Int, player: Player): Boolean { return true } override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { return true } - override fun handleClose(event: InventoryCloseEvent) = dropItems(location) + + private var isSearching = false + + override fun handleClose(event: InventoryCloseEvent) { + if (isSearching) return + dropItems(location) + } + + private fun openSearchMenu(player: Player) { + isSearching = true + + TextInputMenu( + player, + text("Search by Multiblock Name"), + text("Test Description"), + backButtonHandler = { + this.open() + isSearching = false + }, + inputValidator = { input -> + isSearching = true // Double check to make sure this is set whenever something is typed + val searchResults = getSearchResults(input) + + if (searchResults.isNotEmpty()) ValidatorResult.ResultsResult(searchResults.map { text(it.javaClass.simpleName, GRAY).itemName }) + else ValidatorResult.FailureResult(text("No multiblocks found!", RED)) + }, + successfulInputHandler = { + runCatching { + val multiblock = getSearchResults(it).firstOrNull() ?: return@TextInputMenu + multiblockIndex = multiblocks.indexOf(multiblock) + player.closeInventory() + open() + updateConfirmationButton() + + isSearching = false + } + } + ).open() + } + + private fun getSearchResults(input: String): List { + val detectionNames = MultiblockRegistration.byDetectionName.keys() + .filter { detectionName -> input.split(' ').all { splitInput -> detectionName.contains(splitInput, ignoreCase = true) } } + .mapNotNull(MultiblockRegistration::getByStorageName) + + val classNames = MultiblockRegistration.getAllMultiblocks().map { it.javaClass.simpleName } + .filter { className -> input.split(' ').all { splitInput -> className.contains(splitInput, ignoreCase = true) } } + .mapNotNull(MultiblockRegistration::getByStorageName) + + return detectionNames + .plus(classNames) + .distinct() + .filter { if (it.requiredPermission != null) viewer.hasPermission(it.requiredPermission!!) else true } + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 0136bca5ab..91e5cb9ba0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -172,7 +172,7 @@ object MultiblockRegistration : IonServerComponent() { * * E.g. powerbank would contain all tiers of Power Banks **/ - private val byDetectionName : Multimap = multimapOf() + val byDetectionName : Multimap = multimapOf() override fun onEnable() { initMultiblocks() From bdbbc41040b628350f784b6a4ebb0ed81beb18e9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 17 Nov 2024 19:14:47 -0600 Subject: [PATCH 310/500] Add hints for next / prior multiblocks --- .../custom/blocks/MultiblockWorkbench.kt | 38 ++++++++++++++----- .../miscellaneous/utils/text/Formatting.kt | 6 +++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index b4540fccb7..f5b3b85254 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.custom.blocks +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItems @@ -18,7 +19,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.setDisplayNameAndGet import net.horizonsend.ion.server.miscellaneous.utils.text.itemName +import net.horizonsend.ion.server.miscellaneous.utils.text.loreName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN @@ -79,7 +82,6 @@ object MultiblockWorkbench : InteractableCustomBlock( override fun setup(view: InventoryView) { lockedSlots.addAll(BACKGROUND_SLOTS) - setGuiOverlay(view) addGuiButton(LEFT_BUTTON_SLOT, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { it.setCustomModelData(GuiItem.LEFT.customModelData) @@ -103,10 +105,11 @@ object MultiblockWorkbench : InteractableCustomBlock( addGuiButton(CONFIRM_BUTTON_SLOT, ItemStack(Material.BARRIER)) { tryPack() - updateConfirmationButton() + refreshButtons() } - // Perform full setup of the button - updateConfirmationButton() + + // Perform full setup of the buttons + refreshMultiblock(view) isSearching = false } @@ -125,8 +128,23 @@ object MultiblockWorkbench : InteractableCustomBlock( } private fun refreshMultiblock(view: InventoryView) { + internalInventory.getItem(LEFT_BUTTON_SLOT)?.updateMeta { + it.lore(listOf( + if ((multiblockIndex - 1) >= 0) ofChildren( + text("Previous Multiblock: ", GRAY), multiblocks[multiblockIndex - 1].getDisplayName() + ).loreName else text("No previous multiblock", RED).loreName + )) + } + internalInventory.getItem(RIGHT_BUTTON_SLOT)?.updateMeta { + it.lore(listOf( + if ((multiblockIndex + 1) <= multiblocks.lastIndex) ofChildren( + text("Next Multiblock: ", GRAY), multiblocks[multiblockIndex + 1].getDisplayName() + ).loreName else text("No previous multiblock", RED).loreName + )) + } + setGuiOverlay(view) - updateConfirmationButton() + refreshButtons() } private var ready: Boolean = false @@ -134,7 +152,7 @@ object MultiblockWorkbench : InteractableCustomBlock( /** * Update the confirmation button to indicate whether the item requirements are fulfilled **/ - private fun updateConfirmationButton() = Tasks.sync { + private fun refreshButtons() = Tasks.sync { val item = inventory.contents[CONFIRM_BUTTON_SLOT] ?: return@sync val missing = checkRequirements(getUnlockedItems(), currentMultiblock) @@ -179,10 +197,10 @@ object MultiblockWorkbench : InteractableCustomBlock( } // Update after items have been consumed - updateConfirmationButton() + refreshButtons() } - override fun itemChanged(changedSlot: Int, changedItem: ItemStack) = updateConfirmationButton() + override fun itemChanged(changedSlot: Int, changedItem: ItemStack) = refreshButtons() override fun canRemove(slot: Int, player: Player): Boolean { return true } override fun canAdd(itemStack: ItemStack, slot: Int, player: Player): Boolean { return true } @@ -199,7 +217,7 @@ object MultiblockWorkbench : InteractableCustomBlock( TextInputMenu( player, text("Search by Multiblock Name"), - text("Test Description"), + empty(), backButtonHandler = { this.open() isSearching = false @@ -217,7 +235,7 @@ object MultiblockWorkbench : InteractableCustomBlock( multiblockIndex = multiblocks.indexOf(multiblock) player.closeInventory() open() - updateConfirmationButton() + refreshButtons() isSearching = false } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/text/Formatting.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/text/Formatting.kt index 1e3956e75c..c4e44a01ce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/text/Formatting.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/text/Formatting.kt @@ -15,3 +15,9 @@ val Component.itemLore get() = Component.text() .decoration(TextDecoration.ITALIC, false) .append(this) .build() + +val Component.loreName get() = Component.text() + .decoration(TextDecoration.ITALIC, false) + .color(WHITE) + .append(this) + .build() From 76effc782d84e708b43a764b14d30a865375b991 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 17 Nov 2024 19:31:37 -0600 Subject: [PATCH 311/500] Add recipe for multiblock workbench --- .../features/custom/blocks/CustomBlockListeners.kt | 2 -- .../features/custom/blocks/MultiblockWorkbench.kt | 1 + .../server/miscellaneous/registrations/Crafting.kt | 14 +++++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt index 7077a29cd4..a1c976f586 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt @@ -71,8 +71,6 @@ object CustomBlockListeners : SLEventListener() { if (customBlock !is InteractableCustomBlock) return - event.isCancelled = true - when (event.action) { Action.LEFT_CLICK_BLOCK -> customBlock.onLeftClick(event, clickedBlock) Action.RIGHT_CLICK_BLOCK -> customBlock.onRightClick(event, clickedBlock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index f5b3b85254..80c252cc91 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -55,6 +55,7 @@ object MultiblockWorkbench : InteractableCustomBlock( override fun onRightClick(event: PlayerInteractEvent, block: Block) { val player = event.player + event.isCancelled = true cooldown.tryExec(player) { openMenu(player, block.location.toCenterLocation()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt index 1f5bc3cfc0..5e963065a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt @@ -57,6 +57,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.GAS_C import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.GAS_CANISTER_OXYGEN import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.GUN_BARREL import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.MOTHERBOARD +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.MULTIBLOCK_WORKBENCH import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.NETHERITE_CASING import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.PISTOL_RECEIVER import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_ARMOR_BOOTS @@ -140,6 +141,8 @@ import org.bukkit.Material.COBWEB import org.bukkit.Material.COMPOSTER import org.bukkit.Material.COPPER_BLOCK import org.bukkit.Material.COPPER_INGOT +import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.Material.CYAN_WOOL import org.bukkit.Material.DARK_PRISMARINE import org.bukkit.Material.DIAMOND import org.bukkit.Material.DIAMOND_BLOCK @@ -607,7 +610,16 @@ object Crafting : IonServerComponent() { setIngredient('y', SUPERCONDUCTOR_CORE.constructItemStack()) setIngredient('z', FUEL_CONTROL.constructItemStack()) } - shaped("silk_touch_modifier", SILK_TOUCH_MOD.constructItemStack()) { + + itemStackShapeRecipe("multiblock_workbench", MULTIBLOCK_WORKBENCH.constructItemStack()) { + shape("i", "c") + + setIngredient('i', IRON_BLOCK) + setIngredient('c', CRAFTING_TABLE) + } + + // Tool Mods start + itemStackShapeRecipe("silk_touch_modifier", SILK_TOUCH_MOD.constructItemStack()) { shape("gbg", "tst", "ctc") setIngredient('g', RAW_GOLD) From a34f23df5d090c90650f2c31360acb595085feb2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 18 Nov 2024 00:54:36 -0600 Subject: [PATCH 312/500] fix block requirement alias --- .../ion/server/features/multiblock/shape/MultiblockShape.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 7ffb1430d9..5f1d058149 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -310,7 +310,7 @@ class MultiblockShape { fun seaLantern() = type(Material.SEA_LANTERN) fun glassPane() = type(Material.GLASS_PANE) fun stainedGlassPane() = filteredTypes("any stained glass pane") { it.isStainedGlassPane } - fun anyGlassPane(edit: BlockRequirement.() -> Unit = {}) = filteredTypes("any stained glass", edit = edit) { it.isGlassPane } + fun anyGlassPane(edit: BlockRequirement.() -> Unit = {}) = filteredTypes("any stained glass pane", edit = edit) { it.isGlassPane } fun anyStairs(edit: BlockRequirement.() -> Unit = { setExample(Material.STONE_BRICK_STAIRS.createBlockData()) }) = filteredTypes("any stair block", edit) { it.isStairs } From 10425bb14e53942ac34060bc7bf4f4aeb78d5e2c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 19 Nov 2024 01:09:31 -0600 Subject: [PATCH 313/500] Fluid work --- .../server/command/admin/IonChunkCommand.kt | 14 +- .../ion/server/command/qol/SetFluidCommand.kt | 17 +- .../display/fluid/SimpleFluidDisplay.kt | 2 +- .../display/fluid/SplitFluidDisplay.kt | 2 +- .../custom/items/misc/MultimeterItem.kt | 2 +- .../ion/server/features/gas/Gasses.kt | 19 +- .../ion/server/features/gas/type/Gas.kt | 4 +- .../ion/server/features/gas/type/GasFuel.kt | 16 +- .../server/features/gas/type/GasOxidizer.kt | 14 +- .../crafting/ingredient/FluidIngredient.kt | 12 +- .../recipe/take2/LegacyIndustryRecipe.kt | 2 +- .../recipe/take2/result/FluidResult.kt | 4 +- .../type/fluids/BasicFluidStoringEntity.kt | 2 +- .../entity/type/fluids/FluidStoringEntity.kt | 87 ++++++--- .../CategoryRestrictedInternalStorage.kt | 24 ++- .../type/fluids/storage/InternalStorage.kt | 95 ++++----- .../type/fluids/storage/SingleFluidStorage.kt | 22 ++- .../storage/UnlimitedInternalStorage.kt | 20 +- .../entity/type/power/PowerStorage.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 16 +- .../collector/PipedGasCollectorMultiblock.kt | 13 +- .../fluid/storage/FluidStorageMultiblock.kt | 11 +- .../fluids/{PipedFluid.kt => Fluid.kt} | 2 +- .../transport/fluids/FluidRegistry.kt | 53 +++++ .../features/transport/fluids/FluidStack.kt | 6 + .../transport/fluids/TransportedFluids.kt | 47 ----- .../fluids/properties/FluidCategory.kt | 8 +- .../transport/fluids/types/BasicPipedFluid.kt | 2 +- .../types/{GasPipedFluid.kt => GasFluid.kt} | 6 +- .../nodes/cache/FluidTransportCache.kt | 183 +++++++++++++++++- .../nodes/cache/PowerTransportCache.kt | 10 +- .../transport/nodes/cache/TransportCache.kt | 2 +- .../transport/nodes/types/FluidNode.kt | 17 ++ .../features/transport/nodes/types/Node.kt | 6 +- .../transport/util/NodePathfinding.kt | 13 +- .../miscellaneous/registrations/Components.kt | 4 +- 36 files changed, 515 insertions(+), 244 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/{PipedFluid.kt => Fluid.kt} (86%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidStack.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/{GasPipedFluid.kt => GasFluid.kt} (81%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 8fc1213c6d..9aaa83c6a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -9,9 +9,7 @@ import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks -import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node -import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations @@ -78,14 +76,13 @@ object IonChunkCommand : SLCommand() { sender.information("${grid.getRawCache().size} covered position(s).") sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") - grid.getRawCache().forEach { (t, u) -> + grid.getRawCache().forEach { (t, _) -> val vec = toVec3i(t) sender.highlightBlock(vec, 50L) } } @Subcommand("dump extractors") - @CommandCompletion("power") /* |item|gas") */ fun dumpExtractors(sender: Player, network: CacheType) { val ionChunk = sender.chunk.ion() val extractors = network.get(ionChunk).holder.getExtractorManager() @@ -138,11 +135,12 @@ object IonChunkCommand : SLCommand() { } @Subcommand("test extractor") - fun onTick(sender: Player) { - val (node, location) = requireLookingAt(sender, CacheType.POWER) - if (node !is PowerNode.PowerExtractorNode) fail { "Extractor not targeted" } + fun onTick(sender: Player, type: CacheType) { + val (node, location) = requireLookingAt(sender, type) val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } - val grid = CacheType.POWER.get(chunk) as PowerTransportCache + val grid = type.get(chunk) + if (grid.holder.getExtractorManager().isExtractor(location)) fail { "Extractor not targeted" } + grid.tickExtractor(location, 1.0) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt index 4e5575608b..721d6c0dc2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetFluidCommand.kt @@ -11,8 +11,9 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry +import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player @@ -21,21 +22,21 @@ import org.bukkit.entity.Player object SetFluidCommand : SLCommand() { override fun onEnable(manager: PaperCommandManager) { manager.commandCompletions.registerCompletion("fluids") { - TransportedFluids.getAll().map { it.identifier } + FluidRegistry.getAll().map { it.identifier } } - manager.commandContexts.registerContext(PipedFluid::class.java) { + manager.commandContexts.registerContext(Fluid::class.java) { val id = it.popFirstArg() - TransportedFluids[id] ?: throw InvalidCommandArgument("Fluid $id not found!") + FluidRegistry[id] ?: throw InvalidCommandArgument("Fluid $id not found!") } - manager.commandCompletions.setDefaultCompletion("fluids", PipedFluid::class.java) + manager.commandCompletions.setDefaultCompletion("fluids", Fluid::class.java) } @Default @CommandCompletion("@fluids 0|1000|500000|2147483647 main") @Suppress("unused") - fun onSetFluid(sender: Player, fluid: PipedFluid, amount: Int, storeName: String) { + fun onSetFluid(sender: Player, fluid: Fluid, amount: Int, storeName: String) { val selection = runCatching { sender.getSelection() }.getOrNull() ?: fail { "You must make a selection!" } if (sender.world.name != selection.world?.name) return @@ -52,7 +53,7 @@ object SetFluidCommand : SLCommand() { val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) if (entity !is FluidStoringEntity) continue - entity.getNamedStorage(storeName).internalStorage.setContents(fluid, amount) + entity.getNamedStorage(storeName).internalStorage.setContents(FluidStack(fluid, amount)) hits++ sender.debug("power sent") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index fdfd2b52d5..13a9e5b4f3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -16,7 +16,7 @@ class SimpleFluidDisplay( scale: Float ) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { - return ofChildren(formatFluid(), space(), container.internalStorage.getStoredFluid()?.displayName ?: empty) + return ofChildren(formatFluid(), space(), container.internalStorage.getFluidType()?.displayName ?: empty) } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt index 65ba3449df..b053638759 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt @@ -14,6 +14,6 @@ class SplitFluidDisplay( scale: Float ) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { - return ofChildren(container.internalStorage.getStoredFluid()?.displayName ?: empty, newline(), formatFluid()) + return ofChildren(container.internalStorage.getFluidType()?.displayName ?: empty, newline(), formatFluid()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index f929533c37..3f54554918 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -149,7 +149,7 @@ object MultimeterItem : CustomItem("MULTIMETER") { queueRemove(current) visited.add(current.node.position) - val neighbors = getNeighbors(current) + val neighbors = getNeighbors(current, null) if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt index 95a500b749..54cbe5fee4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt @@ -8,13 +8,12 @@ import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.type.Gas import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Location import org.bukkit.inventory.ItemStack -import java.util.concurrent.ThreadLocalRandom import java.util.function.Supplier @Suppress("UNUSED") @@ -30,7 +29,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::hydrogen, - transportedFluidSupplier = Supplier { TransportedFluids.HYDROGEN } + transportedFluidSupplier = Supplier { FluidRegistry.HYDROGEN } ) {} ) val NITROGEN: GasFuel = registerGas( @@ -41,7 +40,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::nitrogen, - transportedFluidSupplier = { TransportedFluids.NITROGEN } + transportedFluidSupplier = { FluidRegistry.NITROGEN } ) {} ) val METHANE: GasFuel = registerGas( @@ -52,7 +51,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.methane.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.methane.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::methane, - transportedFluidSupplier = { TransportedFluids.METHANE } + transportedFluidSupplier = { FluidRegistry.METHANE } ) {} ) @@ -64,7 +63,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_OXYGEN", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.oxygen.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::oxygen, - transportedFluidSupplier = { TransportedFluids.OXYGEN } + transportedFluidSupplier = { FluidRegistry.OXYGEN } ) {} ) val CHLORINE: GasOxidizer = registerGas( @@ -74,7 +73,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_CHLORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.chlorine.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::chlorine, - transportedFluidSupplier = { TransportedFluids.CHLORINE } + transportedFluidSupplier = { FluidRegistry.CHLORINE } ) {} ) val FLUORINE: GasOxidizer = registerGas( @@ -84,7 +83,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_FLUORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.fluorine.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::fluorine, - transportedFluidSupplier = { TransportedFluids.FLUORINE } + transportedFluidSupplier = { FluidRegistry.FLUORINE } ) {} ) @@ -95,7 +94,7 @@ object Gasses : IonServerComponent(false) { displayName = text("Helium", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_HELIUM", configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::helium, - transportedFluidSupplier = { TransportedFluids.HELIUM } + transportedFluidSupplier = { FluidRegistry.HELIUM } ) {} ) val CARBON_DIOXIDE: Gas = registerGas(object : Gas( @@ -103,7 +102,7 @@ object Gasses : IonServerComponent(false) { displayName = text("Carbon Dioxide", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_CARBON_DIOXIDE", configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::carbonDioxide, - transportedFluidSupplier = { TransportedFluids.CARBON_DIOXIDE } + transportedFluidSupplier = { FluidRegistry.CARBON_DIOXIDE } ) {} ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt index db7beea7a0..f9d6e8320b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/Gas.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses import net.horizonsend.ion.server.features.gas.collection.Factor -import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.kyori.adventure.text.Component import org.bukkit.World @@ -14,7 +14,7 @@ abstract class Gas( val containerIdentifier: String, private val configurationSupplier: Supplier, - private val transportedFluidSupplier: Supplier + private val transportedFluidSupplier: Supplier ) { val configuration get() = configurationSupplier.get() val fluid get() = transportedFluidSupplier.get() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt index e3792c8209..007a90b51c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasFuel.kt @@ -1,18 +1,18 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses -import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid import net.kyori.adventure.text.Component import java.util.function.Supplier abstract class GasFuel( - identifier: String, - displayName: Component, - containerIdentifier: String, - configurationSupplier: Supplier, - transportedFluidSupplier: Supplier, + identifier: String, + displayName: Component, + containerIdentifier: String, + configurationSupplier: Supplier, + transportedFluidSupplier: Supplier, - val powerPerUnit: Int, - val cooldown: Int + val powerPerUnit: Int, + val cooldown: Int ) : Gas(identifier, displayName, containerIdentifier, configurationSupplier, transportedFluidSupplier) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt index a04e2d88c7..588065afd1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/type/GasOxidizer.kt @@ -1,16 +1,16 @@ package net.horizonsend.ion.server.features.gas.type import net.horizonsend.ion.server.configuration.Gasses -import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid import net.kyori.adventure.text.Component import java.util.function.Supplier abstract class GasOxidizer( - identifier: String, - displayName: Component, - containerIdentifier: String, - configurationSupplier: Supplier, - transportedFluidSupplier: Supplier, + identifier: String, + displayName: Component, + containerIdentifier: String, + configurationSupplier: Supplier, + transportedFluidSupplier: Supplier, - val powerMultiplier: Double + val powerMultiplier: Double ) : Gas(identifier, displayName, containerIdentifier, configurationSupplier, transportedFluidSupplier) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt index a0e9078367..b823f4c257 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt @@ -3,15 +3,15 @@ package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid -class FluidIngredient(val fluid: PipedFluid, val amount: Int) : MultiblockRecipeIngredient { +class FluidIngredient(val fluid: Fluid, val amount: Int) : MultiblockRecipeIngredient { override fun checkRequirement(context: RecipeExecutionContext): Boolean { val entity = context.entity if (entity !is FluidStoringEntity) return false - return entity.capacities.any { it.internalStorage.getStoredFluid() == fluid && it.internalStorage.getAmount() >= amount } + return entity.fluidStores.any { it.internalStorage.getFluidType() == fluid && it.internalStorage.getAmount() >= amount } } override fun consumeIngredient(context: RecipeExecutionContext): Boolean { @@ -19,8 +19,8 @@ class FluidIngredient(val fluid: PipedFluid, val amount: In if (entity !is FluidStoringEntity) return false - return (entity.capacities.firstOrNull { - it.internalStorage.getStoredFluid() == fluid && it.internalStorage.getAmount() >= amount - }?.internalStorage?.remove(amount) ?: amount) == 0 + return (entity.fluidStores.firstOrNull { + it.internalStorage.getFluidType() == fluid && it.internalStorage.getAmount() >= amount + }?.internalStorage?.removeAmount(amount) ?: amount) == 0 } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt index 066b7400e0..7332a8a2d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt @@ -39,7 +39,7 @@ class LegacyIndustryRecipe( if (resultItem.amount + resultSlot.amount > resultSlot.maxStackSize) return false true } - is FluidResult -> context.entity is FluidStoringEntity && context.entity.canStore(result.fluid, result.amount) + is FluidResult -> context.entity is FluidStoringEntity && context.entity.getCapacityFor(result.fluid.type) >= result.fluid.amount else -> false } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt index cd884584f4..27cf325691 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt @@ -1,5 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.FluidStack -class FluidResult(val fluid: PipedFluid, val amount: Int) : MultiblockRecipeResult() +class FluidResult(val fluid: FluidStack) : MultiblockRecipeResult() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index a44d8a4604..d05cea1c2e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -27,7 +27,7 @@ abstract class BasicFluidStoringEntity( storage: InternalStorage ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { @Suppress("LeakingThis") - override val capacities: Array = arrayOf( + override val fluidStores: Array = arrayOf( loadStoredResource(data, "main", Component.text("Main Storage"), NamespacedKeys.MAIN_STORAGE, storage) ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 217bc16685..dcd01597b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -4,7 +4,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -14,7 +15,7 @@ import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { - val capacities: Array + val fluidStores: Array val fluidInputOffsets: Array fun getFluidInputLocations(): Set { @@ -23,40 +24,59 @@ interface FluidStoringEntity { } /** - * Returns whether any of the internal storages can store the amount of the fluid provided + * Returns the first capacity, if one is available, that can store the fluid stack **/ - fun canStore(fluid: PipedFluid, amount: Int) = capacities.any { it.internalStorage.canStore(fluid, amount) } + fun firstCapacityCanStore(fluid: FluidStack): StorageContainer? { + return fluidStores.firstOrNull { + it.internalStorage.inputAllowed && it.internalStorage.canStore(fluid) + } + } - fun canStore(fluid: PipedFluid) = capacities.any { it.internalStorage.canStore(fluid, 0) } + /** + * Returns whether any capacity can store the fluid stack + **/ + fun anyCapacityCanStore(fluid: FluidStack): Boolean = firstCapacityCanStore(fluid) != null /** - * Returns the first internal storage that can contain the amount of the fluid provided. + * Returns the first capacity, if one is available, that can store the fluid type **/ - fun firstCasStore(fluid: PipedFluid, amount: Int): StorageContainer? = capacities.firstOrNull { it.internalStorage.canStore(fluid, amount) } + fun firstCapacityCanStore(type: Fluid): StorageContainer? { + return fluidStores.firstOrNull { + it.internalStorage.inputAllowed && it.internalStorage.canStore(type) + } + } - fun firstCasStore(fluid: PipedFluid): StorageContainer? = capacities.firstOrNull { it.internalStorage.canStore(fluid, 0) } + /** + * Returns whether any capacity can store the fluid type + **/ + fun anyCapacityCanStore(type: Fluid): Boolean = firstCapacityCanStore(type) != null - fun getCapacityFor(fluid: PipedFluid): Int { - return capacities.sumOf { if (it.internalStorage.canStore(fluid, 0)) it.internalStorage.remainingCapacity() else 0} + fun getCapacityFor(fluid: Fluid): Int { + return fluidStores.sumOf { + if (it.internalStorage.canStore(fluid)) it.internalStorage.remainingCapacity() else 0 + } } - fun isFull(): Boolean = capacities.all { it.internalStorage.isFull() } + fun isFull(): Boolean = fluidStores.all { it.internalStorage.isFull() } - fun isEmpty() = capacities.all { it.internalStorage.isEmpty() } + fun isEmpty() = fluidStores.all { it.internalStorage.isEmpty() } - fun canExtractAny(): Boolean = capacities.any { !it.internalStorage.isEmpty() } + fun canExtractAny(): Boolean = fluidStores.any { !it.internalStorage.isEmpty() } - fun canStoreAny(): Boolean = capacities.any { !it.internalStorage.isFull() && it.internalStorage.inputAllowed } + fun canStoreAny(): Boolean = fluidStores.any { !it.internalStorage.isFull() && it.internalStorage.inputAllowed } /** * Adds the amount of the fluid to the first available internal storage **/ - fun addFirstAvailable(fluid: PipedFluid, amount: Int): Int { - var remaining = amount + fun addFirstAvailable(fluid: FluidStack, debug: Boolean = false): Int { + var remaining = fluid.amount + if (debug) println("Remain ing: $remaining") - for (container in capacities.filter { it.internalStorage.getStoredFluid() == fluid || it.internalStorage.getStoredFluid() == null }) { - val unfit = container.internalStorage.addAmount(fluid, remaining) - remaining -= (remaining - unfit) + for (container in fluidStores.filter { it.internalStorage.canStore(fluid.type) }) { + if (debug) println("Re ing: $remaining") + container.internalStorage.setFluid(fluid.type) + val remainder = container.internalStorage.addAmount(remaining) + remaining -= (remaining - remainder) if (remaining <= 0) break } @@ -67,11 +87,11 @@ interface FluidStoringEntity { /** * Removes the amount of the fluid to the first available internal storage **/ - fun removeFirstAvailable(fluid: PipedFluid, amount: Int): Int { + fun removeFirstAvailable(fluid: Fluid, amount: Int): Int { var remaining = amount - for (container in capacities.filter { it.internalStorage.getStoredFluid() == fluid }) { - val unRemoved = container.internalStorage.remove(fluid, remaining) + for (container in fluidStores.filter { it.internalStorage.getFluidType() == fluid }) { + val unRemoved = container.internalStorage.removeAmount(remaining) remaining -= (remaining - unRemoved) if (remaining <= 0) break @@ -80,15 +100,30 @@ interface FluidStoringEntity { return remaining } - fun getStoredResources() : Map = capacities.associate { it.internalStorage.getStoredFluid() to it.internalStorage.getAmount() } + fun getStoredResources(): Map = fluidStores.associate { it.internalStorage.getFluidType() to it.internalStorage.getAmount() } + + fun getExtractableResources(): Map> { + val entries = mutableMapOf>() + + for (capacity in fluidStores) { + val fluid = capacity.internalStorage.getFluidType() ?: continue + if (!capacity.internalStorage.extractionAllowed) continue + val amount = capacity.internalStorage.getAmount() + if (amount <= 0) continue + + entries[capacity.internalStorage] = fluid to capacity.internalStorage.getAmount() + } + + return entries + } - fun getNamedStorage(name: String): StorageContainer = capacities.first { it.name == name } + fun getNamedStorage(name: String): StorageContainer = fluidStores.first { it.name == name } - fun getStorage(key: NamespacedKey): StorageContainer = capacities.first { it.namespacedKey == key } + fun getStorage(key: NamespacedKey): StorageContainer = fluidStores.first { it.namespacedKey == key } fun storeFluidData(destination: PersistentMultiblockData, context: PersistentDataAdapterContext) { val storages = context.newPersistentDataContainer() - capacities.forEach { it.save(storages) } + fluidStores.forEach { it.save(storages) } destination.addAdditionalData(STORAGES, TAG_CONTAINER, storages) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt index 8877a19ce8..7f4c946be5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/CategoryRestrictedInternalStorage.kt @@ -1,25 +1,29 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.EMPTY +import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory class CategoryRestrictedInternalStorage( private val storageCapacity: Int, override val inputAllowed: Boolean, + override val extractionAllowed: Boolean, private vararg val allowedCategories: FluidCategory, ) : InternalStorage() { override fun getCapacity(): Int = storageCapacity - override fun canStore(resource: PipedFluid, liters: Int): Boolean { - if (liters + getAmount() > getCapacity()) { - return false - } + override fun canStore(fluid: FluidStack): Boolean { + if (!canStore(fluid.type)) return false + return fluid.amount + getAmount() <= getCapacity() + } - // Check that the fluid attempting to be stored is the same as the one currently stored - if (getStoredFluid() != null && resource != getStoredFluid()) { - return false - } + override fun canStore(type: Fluid): Boolean { + if (type == EMPTY) return false // Cannot add an empty fluid stack + if (type == getFluidType()) return true // If it is the same as the current fluid - return allowedCategories.intersect(resource.categories.toSet()).isNotEmpty() + return if (getFluidType() == EMPTY) { // If this is currently empty + allowedCategories.intersect(type.categories.toSet()).isNotEmpty() // Check the category restriction + } else false // Already know its not the stored fluid, so can't store } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt index e58db7f3b1..144722ba5a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/InternalStorage.kt @@ -1,7 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.EMPTY +import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -12,77 +14,80 @@ import org.bukkit.persistence.PersistentDataType * Each internal storage can hold a single type of fluid **/ abstract class InternalStorage { - protected var amountUnsafe: Int = 0 - protected open var fluidUnsafe: PipedFluid? = null + private var amountUnsafe: Int = 0 + protected open var fluidUnsafe: Fluid = EMPTY abstract val inputAllowed: Boolean + abstract val extractionAllowed: Boolean + + protected val mutex: Any = Any() + + fun getFluidType(): Fluid = synchronized(mutex) { fluidUnsafe } + fun getAmount(): Int = synchronized(mutex) { amountUnsafe } abstract fun getCapacity(): Int fun remainingCapacity() = getCapacity() - getAmount() - abstract fun canStore(resource: PipedFluid, liters: Int): Boolean + abstract fun canStore(fluid: FluidStack): Boolean - fun isEmpty(): Boolean = getStoredFluid() == null || getAmount() == 0 + abstract fun canStore(type: Fluid): Boolean - fun isFull(): Boolean = getStoredFluid() != null && getAmount() == getCapacity() - - fun remove(amount: Int): Int { - val newTotal = getAmount() - amount - // negative total will be a remainder - val notRemoved = if (newTotal < 0) -newTotal else 0 + fun isEmpty(): Boolean = getFluidType() == EMPTY || getAmount() == 0 - setAmount(newTotal) + fun isFull(): Boolean = getFluidType() != EMPTY && getAmount() == getCapacity() - return notRemoved - } + fun removeAmount(amount: Int): Int { + val newAmount = synchronized(mutex) { + val newTotal = amountUnsafe - amount + val corrected = newTotal.coerceIn(0, getCapacity()) - fun remove(fluid: PipedFluid, amount: Int): Int { - if (getStoredFluid() != null && fluid != getStoredFluid()) return amount + amountUnsafe = corrected + newTotal + } - if (getStoredFluid() == null) setFluid(fluid) + runUpdates() - return remove(amount) + // negative total will be a remainder + return if (newAmount < 0) -newAmount else 0 } fun addAmount(amount: Int): Int { - val newTotal = getAmount() + amount - val notAdded = if (newTotal > getCapacity()) newTotal - getCapacity() else 0 + val newAmount = synchronized(mutex) { + val newAmount = amountUnsafe + amount + val corrected = newAmount.coerceIn(0, getCapacity()) - setAmount(getAmount() + amount) + amountUnsafe = corrected + newAmount + } - return notAdded - } - - fun addAmount(fluid: PipedFluid, amount: Int): Int { - if (getStoredFluid() != null && fluid != getStoredFluid()) return amount - - if (getStoredFluid() == null) setFluid(fluid) + runUpdates() - return addAmount(amount) + return if (newAmount > getCapacity()) newAmount - getCapacity() else 0 } - fun getStoredFluid(): PipedFluid? = fluidUnsafe - - fun getAmount(): Int = amountUnsafe - - fun setContents(fluid: PipedFluid, amount: Int) { - setFluid(fluid) - setAmount(amount) + fun setContents(fluid: FluidStack) { + setFluid(fluid.type) + setAmount(fluid.amount) } fun setAmount(amount: Int) { - val corrected = amount.coerceIn(0, getCapacity()) + val new = synchronized(mutex) { + val corrected = amount.coerceIn(0, getCapacity()) - this.amountUnsafe = corrected + this.amountUnsafe = corrected + corrected + } - if (corrected == 0) setFluid(null) + if (new == 0) setFluid(EMPTY) runUpdates() } - fun setFluid(fluid: PipedFluid?) { - this.fluidUnsafe = fluid + fun setFluid(fluid: Fluid) { + synchronized(mutex) { + this.fluidUnsafe = fluid + } runUpdates() } @@ -91,7 +96,7 @@ abstract class InternalStorage { * Load storage data from the provided persistent data container **/ fun loadData(pdc: PersistentDataContainer) { - val fluid = pdc.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { TransportedFluids[it] } + val fluid = pdc.get(NamespacedKeys.FLUID, PersistentDataType.STRING)?.let { FluidRegistry[it] } ?: EMPTY val amount = pdc.getOrDefault(NamespacedKeys.FLUID_AMOUNT, PersistentDataType.INTEGER, 0) setFluid(fluid) @@ -102,7 +107,7 @@ abstract class InternalStorage { * Save storage data to the provided persistent data container **/ fun saveData(destination: PersistentDataContainer) { - val fluid = getStoredFluid() ?: return + val fluid = getFluidType() val amount = getAmount() destination.set(NamespacedKeys.FLUID, PersistentDataType.STRING, fluid.identifier) @@ -127,6 +132,6 @@ abstract class InternalStorage { } override fun toString(): String { - return "${javaClass.simpleName}[capacity= ${getCapacity()} fluid= (${getStoredFluid()}, ${getAmount()})]" + return "${javaClass.simpleName}[capacity= ${getCapacity()} fluid= (${getFluidType()}, ${getAmount()})]" } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt index fc9c64320f..724c298584 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/SingleFluidStorage.kt @@ -1,16 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidStack -class SingleFluidStorage(private val storageCapacity: Int, private val restrictedFluid: PipedFluid, override val inputAllowed: Boolean) : InternalStorage() { - override var fluidUnsafe: PipedFluid? = restrictedFluid +class SingleFluidStorage( + private val storageCapacity: Int, + private val allowedFluid: Fluid, + override val inputAllowed: Boolean, + override val extractionAllowed: Boolean +) : InternalStorage() { + override var fluidUnsafe: Fluid = allowedFluid override fun getCapacity(): Int = storageCapacity - override fun canStore(resource: PipedFluid, liters: Int): Boolean { - if (liters + getAmount() > getCapacity()) return false + override fun canStore(fluid: FluidStack): Boolean { + if (!canStore(fluid.type)) return false + return fluid.amount + getAmount() <= getCapacity() + } - // Check that the fluid attempting to be stored is the same as the one currently stored - return (getStoredFluid() == null || resource == restrictedFluid) + override fun canStore(type: Fluid): Boolean { + return type == allowedFluid } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt index 0abe329316..68755fd0ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/storage/UnlimitedInternalStorage.kt @@ -1,17 +1,25 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.EMPTY +import net.horizonsend.ion.server.features.transport.fluids.FluidStack /** * Internal storage with no limits on what fluid can be stored **/ -class UnlimitedInternalStorage(private val storageCapacity: Int, override val inputAllowed: Boolean) : InternalStorage() { +class UnlimitedInternalStorage(private val storageCapacity: Int, override val inputAllowed: Boolean, override val extractionAllowed: Boolean) : InternalStorage() { override fun getCapacity(): Int = storageCapacity - override fun canStore(resource: PipedFluid, liters: Int): Boolean { - if (liters + getAmount() > getCapacity()) return false + override fun canStore(fluid: FluidStack): Boolean { + if (!canStore(fluid.type)) return false + return fluid.amount + getAmount() <= getCapacity() + } + + override fun canStore(type: Fluid): Boolean { + if (type == EMPTY) return false // Cannot add an empty fluid stack + if (type == getFluidType()) return true // If it is the same as the current fluid - // Check that the fluid attempting to be stored is the same as the one currently stored - return !(getStoredFluid() != null && resource != getStoredFluid()) + // Can only store if empty, since we know it isn't the current fluid + return getFluidType() == EMPTY } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt index 158ccee50c..5541ecf4c9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PowerStorage.kt @@ -40,7 +40,7 @@ class PowerStorage(val holder: PoweredMultiblockEntity, amount: Int, val capacit runUpdates() - return if (newAmount > capacity) capacity - newAmount else 0 + return if (newAmount > capacity) newAmount - capacity else 0 } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index f0f2f21615..96b5e2e83d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -26,9 +26,9 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.HYDROGEN -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.OXYGEN -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids.WATER +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.HYDROGEN +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.OXYGEN +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.WATER import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 @@ -212,10 +212,10 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf( - loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER, true)), - loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN, false)), - loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN, false)) + override val fluidStores: Array = arrayOf( + loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER, inputAllowed = true, extractionAllowed = false)), + loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN, inputAllowed = false, extractionAllowed = true)), + loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN, inputAllowed = false, extractionAllowed = true)) ) private val hydrogenStorage by lazy { getNamedStorage("hydrogen_tank") } @@ -231,7 +231,7 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf(Vec3i(0, -1, 0)) - override val capacities: Array = arrayOf( - loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, false, GAS)), - loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, false, GAS)), - loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, false, GAS)), + override val fluidStores: Array = arrayOf( + loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, inputAllowed = false, extractionAllowed = true, GAS)), + loadStoredResource(data, "tank_2", text("Tank 2"), TANK_2, CategoryRestrictedInternalStorage(500, inputAllowed = false, extractionAllowed = true, GAS)), + loadStoredResource(data, "tank_3", text("Tank 3"), TANK_3, CategoryRestrictedInternalStorage(500, inputAllowed = false, extractionAllowed = true, GAS)), ) override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( @@ -147,7 +148,7 @@ object PipedGasCollectorMultiblock : Multiblock(), val fluid = gas.fluid val adjusted = (amount * deltaT).roundToInt() - addFirstAvailable(fluid, adjusted) + addFirstAvailable(FluidStack(fluid, adjusted)) } } @@ -158,7 +159,7 @@ object PipedGasCollectorMultiblock : Multiblock(), } override fun toString(): String { - return "Piped gas collector. Storages: ${capacities.toList()}" + return "Piped gas collector. Storages: ${fluidStores.toList()}" } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 66b73866b8..03feea2f28 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -44,8 +44,17 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM z: Int, world: World, structureDirection: BlockFace, - ) : BasicFluidStoringEntity(manager, multiblock, data, x, y, z, world, structureDirection, UnlimitedInternalStorage(multiblock.capacity, true)), FluidStoringEntity, DisplayMultiblockEntity { + ) : BasicFluidStoringEntity( + manager, + multiblock, + data, + x, y, z, + world, + structureDirection, + UnlimitedInternalStorage(multiblock.capacity, inputAllowed = true, extractionAllowed = true) + ), FluidStoringEntity, DisplayMultiblockEntity { override val fluidInputOffset: Vec3i = Vec3i(0, -1, 0) + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, SplitFluidDisplay(mainStorage, +0.0, -0.0, +0.0, 0.45f), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt index 0d629e5ec4..31bf261b1d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/PipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/Fluid.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.fluids import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory import net.kyori.adventure.text.Component -abstract class PipedFluid(val identifier: String) { +abstract class Fluid(val identifier: String) { abstract val displayName: Component abstract val categories: Array diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt new file mode 100644 index 0000000000..d5fc7730ea --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt @@ -0,0 +1,53 @@ +package net.horizonsend.ion.server.features.transport.fluids + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.gas.Gasses +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.BLUE +import net.kyori.adventure.text.format.NamedTextColor.WHITE +import java.util.concurrent.ConcurrentHashMap + + +object FluidRegistry : IonServerComponent() { + private val fluids = mutableListOf() + private val byIdentifier = ConcurrentHashMap() + + val EMPTY = register(object : Fluid("EMPTY") { + override val displayName: Component = text("Empty", WHITE) + override val categories: Array = arrayOf() + }) + + val HYDROGEN = register(GasFluid("HYDROGEN") { Gasses.HYDROGEN }) + val NITROGEN = register(GasFluid("NITROGEN") { Gasses.NITROGEN }) + val METHANE = register(GasFluid("METHANE") { Gasses.METHANE }) + val OXYGEN = register(GasFluid("OXYGEN") { Gasses.OXYGEN }) + val CHLORINE = register(GasFluid("CHLORINE") { Gasses.CHLORINE }) + val FLUORINE = register(GasFluid("FLUORINE") { Gasses.FLUORINE }) + val HELIUM = register(GasFluid("FLUORINE") { Gasses.FLUORINE }) + val CARBON_DIOXIDE = register(GasFluid("FLUORINE") { Gasses.FLUORINE }) + val WATER = register(object : Fluid("WATER") { + override val displayName: Component = text("Water", BLUE) + override val categories: Array = arrayOf() + }) + + init { + fluids.associateByTo(byIdentifier) { it.identifier } + } + + fun register(fluid: T): T { + fluids.add(fluid) + + fluid.categories.forEach { it.addMember(fluid) } + + return fluid + } + + operator fun get(identifier: String): Fluid? { + return byIdentifier[identifier] + } + + fun getAll() = fluids +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidStack.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidStack.kt new file mode 100644 index 0000000000..72e0d81238 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidStack.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.fluids + +data class FluidStack( + var type: Fluid, + var amount: Int +) : Cloneable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt deleted file mode 100644 index 89c60a09f2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/TransportedFluids.kt +++ /dev/null @@ -1,47 +0,0 @@ -package net.horizonsend.ion.server.features.transport.fluids - -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.gas.Gasses -import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory -import net.horizonsend.ion.server.features.transport.fluids.types.GasPipedFluid -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor.BLUE -import java.util.concurrent.ConcurrentHashMap - -// -object TransportedFluids : IonServerComponent() { - private val pipedFluids = mutableListOf() - private val byIdentifier = ConcurrentHashMap() - - val HYDROGEN = register(GasPipedFluid("HYDROGEN") { Gasses.HYDROGEN }) - val NITROGEN = register(GasPipedFluid("NITROGEN") { Gasses.NITROGEN }) - val METHANE = register(GasPipedFluid("METHANE") { Gasses.METHANE }) - val OXYGEN = register(GasPipedFluid("OXYGEN") { Gasses.OXYGEN }) - val CHLORINE = register(GasPipedFluid("CHLORINE") { Gasses.CHLORINE }) - val FLUORINE = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) - val HELIUM = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) - val CARBON_DIOXIDE = register(GasPipedFluid("FLUORINE") { Gasses.FLUORINE }) - val WATER = register(object : PipedFluid("WATER") { - override val displayName: Component = text("Water", BLUE) - override val categories: Array = arrayOf() - }) - - init { - pipedFluids.associateByTo(byIdentifier) { it.identifier } - } - - fun register(fluid: T): T { - pipedFluids.add(fluid) - - fluid.categories.forEach { it.addMember(fluid) } - - return fluid - } - - operator fun get(identifier: String): PipedFluid? { - return byIdentifier[identifier] - } - - fun getAll() = pipedFluids -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt index f9b06c99bf..7c20258ffc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/properties/FluidCategory.kt @@ -2,16 +2,16 @@ package net.horizonsend.ion.server.features.transport.fluids.properties import com.manya.pdc.DataTypes import com.manya.pdc.base.EnumDataType -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid enum class FluidCategory { GAS; - private val members = mutableListOf() + private val members = mutableListOf() - fun getMembers(): List = members + fun getMembers(): List = members - fun addMember(fluid: PipedFluid) = members.add(fluid) + fun addMember(fluid: Fluid) = members.add(fluid) companion object { val persistentDataType = EnumDataType(FluidCategory::class.java) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt index 2309c13abb..0b562773af 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt @@ -1,4 +1,4 @@ package net.horizonsend.ion.server.features.transport.fluids.types -class BasicPipedFluid /*: PipedFluid()*/ { +class BasicPipedFluid /*: Fluid()*/ { } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt similarity index 81% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt index 31bd0157e9..dcf228f051 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasPipedFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt @@ -1,15 +1,15 @@ package net.horizonsend.ion.server.features.transport.fluids.types import net.horizonsend.ion.server.features.gas.type.Gas -import net.horizonsend.ion.server.features.transport.fluids.PipedFluid +import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory import net.kyori.adventure.text.Component import java.util.function.Supplier -class GasPipedFluid( +class GasFluid( identifier: String, private val gasSupplier: Supplier, -) : PipedFluid(identifier) { +) : Fluid(identifier) { override val categories: Array = arrayOf(FluidCategory.GAS) override val displayName: Component get() = gas.displayName diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index ec8762c994..65fb332bce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -3,9 +3,15 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -13,6 +19,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TY import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.WAXED_CHISELED_COPPER @@ -20,6 +27,7 @@ import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod import kotlin.math.roundToInt @@ -27,14 +35,11 @@ class FluidTransportCache(holder: CacheHolder): TransportCa override val type: CacheType = CacheType.FLUID override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addDataHandler(Material.LIGHTNING_ROD) { data, _ -> FluidNode.LightningRodNode(data.facing.axis) } - .addSimpleNode(WAXED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_CHISELED_COPPER) } .addSimpleNode(WAXED_EXPOSED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_EXPOSED_CHISELED_COPPER) } .addSimpleNode(WAXED_WEATHERED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_WEATHERED_CHISELED_COPPER) } .addSimpleNode(WAXED_OXIDIZED_COPPER) { FluidNode.FluidJunctionNode(WAXED_OXIDIZED_COPPER) } - - .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { FluidNode.FluidJunctionNode(CRAFTING_TABLE) } - + .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { FluidNode.FluidJunctionNode(CRAFTING_TABLE) } // All unwaxed chiseled are a single channel .addSimpleNode(CRAFTING_TABLE, FluidNode.FluidExtractorNode) .addSimpleNode(Material.FLETCHING_TABLE, FluidNode.FluidInputNode) .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) @@ -45,18 +50,45 @@ class FluidTransportCache(holder: CacheHolder): TransportCa override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() val sources = getFluidExtractorSourcePool(location, world) + println("Sources: $sources") val source = sources.randomOrNull() ?: return@submit //TODO take from all if (source.getStoredResources().isEmpty()) return@submit // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(CacheType.POWER, world, location) { node -> + val destinations: List = getNetworkDestinations(type, world, location) { node -> world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } } + println("Destinations: ${destinations.size}") + if (destinations.isEmpty()) return@submit val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxFluidRemovedPerExtractorTick * delta).roundToInt() + val resources = source.getExtractableResources() + + for ((storage, avail) in resources) { + val (fluid, amount) = avail + val transferred = minOf(amount, transferLimit) + + val missing = storage.removeAmount(transferred) + val remainder = runFluidTransfer( + Node.NodePositionData( + FluidNode.FluidExtractorNode, + world, + location, + BlockFace.SELF + ), + destinations, + fluid, + transferred - missing + ) + + if (remainder > 0) { + storage.setFluid(fluid) + storage.addAmount(remainder) + } + } } } private fun getFluidExtractorSourcePool(extractorLocation: BlockKey, world: World): List { @@ -64,8 +96,13 @@ class FluidTransportCache(holder: CacheHolder): TransportCa for (face in ADJACENT_BLOCK_FACES) { val inputLocation = getRelative(extractorLocation, face) - if (holder.getOrCacheGlobalNode(inputLocation) !is FluidNode.FluidInputNode) continue - val entities = getInputEntities(world, inputLocation) + if (holder.getOrCacheGlobalNode(inputLocation) !is FluidNode.FluidInputNode) { + println("$face isn't a input") + continue + } + val entities = getInputEntities(world, type, inputLocation) + + println("entities: $entities") for (entity in entities) { if (entity !is FluidStoringEntity) continue @@ -75,4 +112,136 @@ class FluidTransportCache(holder: CacheHolder): TransportCa return sources } + + fun runFluidTransfer(source: Node.NodePositionData, rawDestinations: List, fluid: Fluid, amount: Int): Int { + println("Transferring $amount $fluid from ${toVec3i(source.position)} to ${rawDestinations.size}") + if (rawDestinations.isEmpty()) return amount + + val filteredDestinations = rawDestinations.filter { destinationLoc -> + getInputEntities(holder.getWorld(), type, destinationLoc).any { it is FluidStoringEntity && it.anyCapacityCanStore(fluid) } + } + + println("$filteredDestinations destinations filtered") + + if (filteredDestinations.isEmpty()) return amount + + println("1") + + val numDestinations = filteredDestinations.size + + val paths: Array?> = Array(numDestinations) { runCatching { + getIdealPath(source, filteredDestinations[it]) { node, _ -> node is FluidNode && node.canTransport(fluid) } + }.getOrNull() } + + var maximumResistance: Double = -1.0 + + println("max resistance: $maximumResistance") + + // Perform the calc & max find in the same loop + val pathResistance: Array = Array(numDestinations) { + val res = calculatePathResistance(paths[it]) + if (res != null && maximumResistance < res) maximumResistance = res + + res + } + + println("max resistance: $maximumResistance") + + // All null, no paths found + if (maximumResistance == -1.0) return amount + + var shareFactorSum = 0.0 + + // Get a parallel array containing the ascending order of resistances + val sortedIndexes = getSorted(pathResistance) + + val shareFactors: Array = Array(numDestinations) { index -> + val resistance = pathResistance[index] ?: return@Array null + val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) + shareFactorSum += fac + + fac + } + + var remainingAmount = amount + + for ((index, destination) in filteredDestinations.withIndex()) { + println("Transferring index $index to ${toVec3i(destination)}") + + val shareFactor = shareFactors[index] ?: continue + println("Share factor: $shareFactor") + val inputData = FluidNode.FluidInputNode.getFluidEntities(source.world, destination) + println("Input entities: ${inputData.size}") + + val share = shareFactor / shareFactorSum + println("Share: $share") + println("Amount: $amount") + + val idealSend = (amount * share).roundToInt() + println("IdealSend: $idealSend") + val capacity = getRemainingCapacity(fluid, inputData) + println("Capacity: $capacity") + val toSend = minOf(idealSend, capacity) + + println("toSend: $toSend") + + // Amount of power that didn't fit + val remainder = distributeFluid(inputData, fluid, toSend) + println("Distributed, $remainder remaining") + val realTaken = toSend - remainder + + remainingAmount -= realTaken + completeChain(paths[index], realTaken) + + if (remainder == 0) continue + + // Get the proportion of the amount of power that sent compared to the ideal calculations. + val usedShare = realTaken.toDouble() / idealSend.toDouble() + // Use that to get a proportion of the share factor, and remove that from the sum. + val toRemove = shareFactor * usedShare + shareFactorSum -= toRemove + } + + return remainingAmount + } + + private fun getRemainingCapacity(fluid: Fluid, destinations: List): Int { + return destinations.sumOf { it.getCapacityFor(fluid) } + } + + fun distributeFluid(destinations: List, fluid: Fluid, amount: Int): Int { + val entities = destinations.filterTo(mutableListOf()) { it.getCapacityFor(fluid) > 0 } + if (entities.isEmpty()) return amount + + // Skip math for most scenarios + println("entities.size: ${entities.size}") + if (entities.size == 1) return entities.first().addFirstAvailable(FluidStack(fluid, amount), true) + + var remainingPower = amount + + while (remainingPower > 0) { + if (entities.isEmpty()) break + + val share = remainingPower / entities.size + val minRemaining = entities.minOf { it.getCapacityFor(fluid) } + val distributed = minOf(minRemaining, share) + + val iterator = entities.iterator() + while (iterator.hasNext()) { + val entity = iterator.next() + + val r = entity.addFirstAvailable(FluidStack(fluid, amount), true) + if (r > 0) iterator.remove() + + remainingPower -= (distributed - r) + } + } + + return remainingPower + } + + + private fun completeChain(path: Array?, transferred: Int) { + path?.forEach { if (it.type is PowerNode.PowerFlowMeter) it.type.onCompleteChain(transferred) } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index fafb91c548..84c1a368e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -87,7 +87,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC for (face in ADJACENT_BLOCK_FACES) { val inputLocation = getRelative(extractorLocation, face) if (holder.getOrCacheGlobalNode(inputLocation) !is PowerInputNode) continue - val entities = getInputEntities(world, inputLocation) + val entities = getInputEntities(world, type, inputLocation) for (entity in entities) { if (entity !is PoweredMultiblockEntity) continue @@ -106,9 +106,11 @@ class PowerTransportCache(holder: CacheHolder) : TransportC if (rawDestinations.isEmpty()) return availableTransferPower val filteredDestinations = rawDestinations.filter { destinationLoc -> - getInputEntities(holder.getWorld(), destinationLoc).any { it is PoweredMultiblockEntity && !it.powerStorage.isFull() } + getInputEntities(holder.getWorld(), type, destinationLoc).any { it is PoweredMultiblockEntity && !it.powerStorage.isFull() } } + if (filteredDestinations.isEmpty()) return availableTransferPower + val numDestinations = filteredDestinations.size val paths: Array?> = Array(numDestinations) { runCatching { @@ -176,9 +178,9 @@ class PowerTransportCache(holder: CacheHolder) : TransportC * Gets the powered entities accessible from this location, assuming it is an input * This method is used in conjunction with input registration to allow direct access via signs, and remote access via registered inputs **/ -fun getInputEntities(world: World, location: BlockKey): Set { +fun getInputEntities(world: World, type: CacheType, location: BlockKey): Set { val inputManager = world.ion.inputManager - val registered = inputManager.getHolders(CacheType.POWER, location) + val registered = inputManager.getHolders(type, location) val adjacentBlocks = stupidOffsets.mapNotNull { MultiblockEntities.getMultiblockEntity(world, it.x, it.y, it.z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index ed66068a58..d186a8c047 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block -abstract class TransportCache(val holder: CacheHolder<*> /* TODO temp network holder, works for now */) { +abstract class TransportCache(val holder: CacheHolder<*>) { private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() private val mutex = Any() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt index 942a6f1a87..2ccef0554a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt @@ -1,22 +1,33 @@ package net.horizonsend.ion.server.features.transport.nodes.types +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.faces import org.bukkit.Axis import org.bukkit.Material +import org.bukkit.World import org.bukkit.block.BlockFace sealed interface FluidNode : Node { override val cacheType: CacheType get() = CacheType.FLUID + /** + * Used for filters + **/ + fun canTransport(fluid: Fluid): Boolean + data class FluidJunctionNode(val channel: Material) : FluidNode { override val pathfindingResistance: Double = 1.0 override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = if (other is FluidJunctionNode) other.channel == channel else true override fun canTransferTo(other: Node, offset: BlockFace): Boolean = if (other is FluidJunctionNode) other.channel == channel else true override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun canTransport(fluid: Fluid): Boolean = true } data class LightningRodNode(var axis: Axis) : FluidNode, ComplexNode { @@ -27,6 +38,7 @@ sealed interface FluidNode : Node { override fun onTranslate(movement: StarshipMovement) { this.axis = movement.displaceFace(this.axis.faces.first).axis } + override fun canTransport(fluid: Fluid): Boolean = true } data object FluidExtractorNode : FluidNode { @@ -34,6 +46,7 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is FluidInputNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun canTransport(fluid: Fluid): Boolean = true } data object FluidInputNode : FluidNode { @@ -41,6 +54,8 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun canTransport(fluid: Fluid): Boolean = true + fun getFluidEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.FLUID, location).filterIsInstance() } data object FluidMergeNode : FluidNode { @@ -48,6 +63,7 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is FluidJunctionNode override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is FluidJunctionNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun canTransport(fluid: Fluid): Boolean = true } data object FluidInvertedMergeNode : FluidNode { @@ -55,5 +71,6 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is LightningRodNode override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is LightningRodNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun canTransport(fluid: Fluid): Boolean = true } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt index 5de8c49c24..5444d0e1b1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt @@ -23,7 +23,7 @@ interface Node { **/ fun canTransferFrom(other: Node, offset: BlockFace): Boolean - fun getNextNodes(world: World, position: BlockKey, backwards: BlockFace): List { + fun getNextNodes(world: World, position: BlockKey, backwards: BlockFace, filter: ((Node, BlockFace) -> Boolean)?): List { val adjacent = getTransferableDirections(backwards) val nodes = mutableListOf() @@ -32,6 +32,7 @@ interface Node { val cached = getOrCacheNode(cacheType, world, pos) ?: continue if (!cached.canTransferFrom(this, adjacentFace) || !canTransferTo(cached, adjacentFace)) continue + if (filter != null && !filter.invoke(cached, adjacentFace)) continue nodes.add(NodePositionData(cached, world, getRelative(position, adjacentFace), adjacentFace)) } @@ -40,7 +41,8 @@ interface Node { } data class NodePositionData(val type: Node, val world: World, val position: BlockKey, val offset: BlockFace) { - fun getNextNodes(): List = type.getNextNodes(world, position, offset.oppositeFace) + fun getNextNodes(filter: ((Node, BlockFace) -> Boolean)?): List = + type.getNextNodes(world, position, offset.oppositeFace, filter) } fun onInvalidate() {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index dfc6c9210a..b05ee07d29 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -28,7 +28,8 @@ inline fun getNetworkDestinations(cacheType: CacheType, world: visitQueue.addAll(originNode.getNextNodes( world = world, position = originPos, - backwards = BlockFace.SELF + backwards = BlockFace.SELF, + null )) while (visitQueue.isNotEmpty()) { @@ -37,7 +38,7 @@ inline fun getNetworkDestinations(cacheType: CacheType, world: if (current.type is T && check(current)) destinations.add(current.position) - visitQueue.addAll(current.getNextNodes().filterNot { visited.contains(it.position) || visitQueue.contains(it) }) + visitQueue.addAll(current.getNextNodes(null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) } return destinations.toList() @@ -46,7 +47,7 @@ inline fun getNetworkDestinations(cacheType: CacheType, world: /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ -fun getIdealPath(from: Node.NodePositionData, to: BlockKey): Array? { +fun getIdealPath(from: Node.NodePositionData, to: BlockKey, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -83,7 +84,7 @@ fun getIdealPath(from: Node.NodePositionData, to: BlockKey): Array { - val transferable = current.node.getNextNodes() +fun getNeighbors(current: PathfindingNodeWrapper, filter: ((Node, BlockFace) -> Boolean)?): Array { + val transferable = current.node.getNextNodes(filter) return Array(transferable.size) { val next = transferable[it] diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 133250e617..229aa007df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -91,7 +91,7 @@ import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeacons import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCooldown import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.fluids.TransportedFluids +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.old.Wires @@ -167,7 +167,7 @@ val components: List = listOf( ShipmentManager, Gasses, - TransportedFluids, + FluidRegistry, Bazaars, Merchants, From 5ef2d97b0aabc4e792045b924ec8c6c01d1ecea0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 19 Nov 2024 11:00:00 -0600 Subject: [PATCH 314/500] Remove printlns --- .../entity/type/fluids/FluidStoringEntity.kt | 4 +-- .../nodes/cache/FluidTransportCache.kt | 32 ++----------------- 2 files changed, 3 insertions(+), 33 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index dcd01597b0..02f32c161f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -68,12 +68,10 @@ interface FluidStoringEntity { /** * Adds the amount of the fluid to the first available internal storage **/ - fun addFirstAvailable(fluid: FluidStack, debug: Boolean = false): Int { + fun addFirstAvailable(fluid: FluidStack): Int { var remaining = fluid.amount - if (debug) println("Remain ing: $remaining") for (container in fluidStores.filter { it.internalStorage.canStore(fluid.type) }) { - if (debug) println("Re ing: $remaining") container.internalStorage.setFluid(fluid.type) val remainder = container.internalStorage.addAmount(remaining) remaining -= (remaining - remainder) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 65fb332bce..ab7fac8fd7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -19,7 +19,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TY import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.WAXED_CHISELED_COPPER @@ -50,7 +49,6 @@ class FluidTransportCache(holder: CacheHolder): TransportCa override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() val sources = getFluidExtractorSourcePool(location, world) - println("Sources: $sources") val source = sources.randomOrNull() ?: return@submit //TODO take from all if (source.getStoredResources().isEmpty()) return@submit @@ -60,8 +58,6 @@ class FluidTransportCache(holder: CacheHolder): TransportCa world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } } - println("Destinations: ${destinations.size}") - if (destinations.isEmpty()) return@submit val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxFluidRemovedPerExtractorTick * delta).roundToInt() @@ -97,13 +93,10 @@ class FluidTransportCache(holder: CacheHolder): TransportCa for (face in ADJACENT_BLOCK_FACES) { val inputLocation = getRelative(extractorLocation, face) if (holder.getOrCacheGlobalNode(inputLocation) !is FluidNode.FluidInputNode) { - println("$face isn't a input") continue } val entities = getInputEntities(world, type, inputLocation) - println("entities: $entities") - for (entity in entities) { if (entity !is FluidStoringEntity) continue sources.add(entity) @@ -114,19 +107,14 @@ class FluidTransportCache(holder: CacheHolder): TransportCa } fun runFluidTransfer(source: Node.NodePositionData, rawDestinations: List, fluid: Fluid, amount: Int): Int { - println("Transferring $amount $fluid from ${toVec3i(source.position)} to ${rawDestinations.size}") if (rawDestinations.isEmpty()) return amount val filteredDestinations = rawDestinations.filter { destinationLoc -> getInputEntities(holder.getWorld(), type, destinationLoc).any { it is FluidStoringEntity && it.anyCapacityCanStore(fluid) } } - println("$filteredDestinations destinations filtered") - if (filteredDestinations.isEmpty()) return amount - println("1") - val numDestinations = filteredDestinations.size val paths: Array?> = Array(numDestinations) { runCatching { @@ -135,8 +123,6 @@ class FluidTransportCache(holder: CacheHolder): TransportCa var maximumResistance: Double = -1.0 - println("max resistance: $maximumResistance") - // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { val res = calculatePathResistance(paths[it]) @@ -145,8 +131,6 @@ class FluidTransportCache(holder: CacheHolder): TransportCa res } - println("max resistance: $maximumResistance") - // All null, no paths found if (maximumResistance == -1.0) return amount @@ -166,28 +150,17 @@ class FluidTransportCache(holder: CacheHolder): TransportCa var remainingAmount = amount for ((index, destination) in filteredDestinations.withIndex()) { - println("Transferring index $index to ${toVec3i(destination)}") - val shareFactor = shareFactors[index] ?: continue - println("Share factor: $shareFactor") val inputData = FluidNode.FluidInputNode.getFluidEntities(source.world, destination) - println("Input entities: ${inputData.size}") val share = shareFactor / shareFactorSum - println("Share: $share") - println("Amount: $amount") val idealSend = (amount * share).roundToInt() - println("IdealSend: $idealSend") val capacity = getRemainingCapacity(fluid, inputData) - println("Capacity: $capacity") val toSend = minOf(idealSend, capacity) - println("toSend: $toSend") - // Amount of power that didn't fit val remainder = distributeFluid(inputData, fluid, toSend) - println("Distributed, $remainder remaining") val realTaken = toSend - remainder remainingAmount -= realTaken @@ -214,8 +187,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa if (entities.isEmpty()) return amount // Skip math for most scenarios - println("entities.size: ${entities.size}") - if (entities.size == 1) return entities.first().addFirstAvailable(FluidStack(fluid, amount), true) + if (entities.size == 1) return entities.first().addFirstAvailable(FluidStack(fluid, amount)) var remainingPower = amount @@ -230,7 +202,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa while (iterator.hasNext()) { val entity = iterator.next() - val r = entity.addFirstAvailable(FluidStack(fluid, amount), true) + val r = entity.addFirstAvailable(FluidStack(fluid, amount)) if (r > 0) iterator.remove() remainingPower -= (distributed - r) From 5095bebb2346211f35a5ac1707203a3256cb3714 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 19 Nov 2024 11:51:28 -0600 Subject: [PATCH 315/500] Transport code cleanup --- .../nodes/cache/FluidTransportCache.kt | 34 +--- .../nodes/cache/PowerTransportCache.kt | 152 ++++-------------- .../transport/nodes/cache/TransportCache.kt | 85 ++++++++++ 3 files changed, 125 insertions(+), 146 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index ab7fac8fd7..3aacf5be17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -14,18 +14,15 @@ import net.horizonsend.ion.server.features.transport.util.calculatePathResistanc import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.WAXED_CHISELED_COPPER import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER -import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod import kotlin.math.roundToInt @@ -48,7 +45,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() - val sources = getFluidExtractorSourcePool(location, world) + val sources = getExtractorSources(location) { it.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all if (source.getStoredResources().isEmpty()) return@submit @@ -87,30 +84,14 @@ class FluidTransportCache(holder: CacheHolder): TransportCa } } } - private fun getFluidExtractorSourcePool(extractorLocation: BlockKey, world: World): List { - val sources = mutableListOf() - - for (face in ADJACENT_BLOCK_FACES) { - val inputLocation = getRelative(extractorLocation, face) - if (holder.getOrCacheGlobalNode(inputLocation) !is FluidNode.FluidInputNode) { - continue - } - val entities = getInputEntities(world, type, inputLocation) - - for (entity in entities) { - if (entity !is FluidStoringEntity) continue - sources.add(entity) - } - } - - return sources - } - - fun runFluidTransfer(source: Node.NodePositionData, rawDestinations: List, fluid: Fluid, amount: Int): Int { + /** + * Executes the transfer from the source node to the lit of destinations. Transports one fluid at a time. + **/ + private fun runFluidTransfer(source: Node.NodePositionData, rawDestinations: List, fluid: Fluid, amount: Int): Int { if (rawDestinations.isEmpty()) return amount val filteredDestinations = rawDestinations.filter { destinationLoc -> - getInputEntities(holder.getWorld(), type, destinationLoc).any { it is FluidStoringEntity && it.anyCapacityCanStore(fluid) } + getInputEntities(destinationLoc).any { it is FluidStoringEntity && it.anyCapacityCanStore(fluid) } } if (filteredDestinations.isEmpty()) return amount @@ -182,7 +163,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa return destinations.sumOf { it.getCapacityFor(fluid) } } - fun distributeFluid(destinations: List, fluid: Fluid, amount: Int): Int { + private fun distributeFluid(destinations: List, fluid: Fluid, amount: Int): Int { val entities = destinations.filterTo(mutableListOf()) { it.getCapacityFor(fluid) > 0 } if (entities.isEmpty()) return amount @@ -212,7 +193,6 @@ class FluidTransportCache(holder: CacheHolder): TransportCa return remainingPower } - private fun completeChain(path: Array?, transferred: Int) { path?.forEach { if (it.type is PowerNode.PowerFlowMeter) it.type.onCompleteChain(transferred) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 84c1a368e5..7796d99db2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,8 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.MultiblockEntities -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder @@ -15,11 +13,8 @@ import net.horizonsend.ion.server.features.transport.util.calculatePathResistanc import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.Material.END_ROD import org.bukkit.Material.IRON_BLOCK @@ -28,7 +23,6 @@ import org.bukkit.Material.NOTE_BLOCK import org.bukkit.Material.OBSERVER import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE -import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod @@ -49,7 +43,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { val world = holder.getWorld() - val sources = getPowerExtractorSourcePool(location, world) + val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power @@ -81,24 +75,6 @@ class PowerTransportCache(holder: CacheHolder) : TransportC } }} - private fun getPowerExtractorSourcePool(extractorLocation: BlockKey, world: World): List { - val sources = mutableListOf() - - for (face in ADJACENT_BLOCK_FACES) { - val inputLocation = getRelative(extractorLocation, face) - if (holder.getOrCacheGlobalNode(inputLocation) !is PowerInputNode) continue - val entities = getInputEntities(world, type, inputLocation) - - for (entity in entities) { - if (entity !is PoweredMultiblockEntity) continue - if (entity.powerStorage.isEmpty()) continue - sources.add(entity) - } - } - - return sources - } - /** * Runs the power transfer from the source to the destinations. pending rewrite **/ @@ -106,7 +82,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC if (rawDestinations.isEmpty()) return availableTransferPower val filteredDestinations = rawDestinations.filter { destinationLoc -> - getInputEntities(holder.getWorld(), type, destinationLoc).any { it is PoweredMultiblockEntity && !it.powerStorage.isFull() } + getInputEntities(destinationLoc).any { it is PoweredMultiblockEntity && !it.powerStorage.isFull() } } if (filteredDestinations.isEmpty()) return availableTransferPower @@ -152,14 +128,20 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val share = shareFactor / shareFactorSum val idealSend = (availableTransferPower * share).roundToInt() - val toSend = minOf(idealSend, getRemainingCapacity(inputData)) + val remainingCapacity = inputData.sumOf { it.powerStorage.getRemainingCapacity() } + + val toSend = minOf(idealSend, remainingCapacity) // Amount of power that didn't fit val remainder = distributePower(inputData, toSend) val realTaken = toSend - remainder remainingPower -= realTaken - completeChain(paths[index], realTaken) + + runCatching { + // Update power flow meters + paths[index]?.forEach { if (it.type is PowerFlowMeter) it.type.onCompleteChain(realTaken) } + } if (remainder == 0) continue @@ -172,106 +154,38 @@ class PowerTransportCache(holder: CacheHolder) : TransportC return remainingPower } -} - -/** - * Gets the powered entities accessible from this location, assuming it is an input - * This method is used in conjunction with input registration to allow direct access via signs, and remote access via registered inputs - **/ -fun getInputEntities(world: World, type: CacheType, location: BlockKey): Set { - val inputManager = world.ion.inputManager - val registered = inputManager.getHolders(type, location) - - val adjacentBlocks = stupidOffsets.mapNotNull { MultiblockEntities.getMultiblockEntity(world, it.x, it.y, it.z) } - - return registered.plus(adjacentBlocks) -} -/** - * Distributes power to the provided list of entities - * Returns the amount that would not fit - **/ -fun distributePower(destinations: List, power: Int): Int { - val entities = destinations.filterTo(mutableListOf()) { !it.powerStorage.isFull() } - if (entities.isEmpty()) return power - - // Skip math for most scenarios - if (entities.size == 1) return entities.first().powerStorage.addPower(power) - - var remainingPower = power + /** + * Distributes power to the provided list of entities + * Returns the amount that would not fit + **/ + private fun distributePower(destinations: List, power: Int): Int { + val entities = destinations.filterTo(mutableListOf()) { !it.powerStorage.isFull() } + if (entities.isEmpty()) return power - while (remainingPower > 0) { - if (entities.isEmpty()) break + // Skip math for most scenarios + if (entities.size == 1) return entities.first().powerStorage.addPower(power) - val share = remainingPower / entities.size - val minRemaining = entities.minOf { it.powerStorage.getRemainingCapacity() } - val distributed = minOf(minRemaining, share) + var remainingPower = power - val iterator = entities.iterator() - while (iterator.hasNext()) { - val entity = iterator.next() + while (remainingPower > 0) { + if (entities.isEmpty()) break - val r = entity.powerStorage.addPower(distributed) - if (entity.powerStorage.isFull()) iterator.remove() + val share = remainingPower / entities.size + val minRemaining = entities.minOf { it.powerStorage.getRemainingCapacity() } + val distributed = minOf(minRemaining, share) - remainingPower -= (distributed - r) - } - } + val iterator = entities.iterator() + while (iterator.hasNext()) { + val entity = iterator.next() - return remainingPower -} + val r = entity.powerStorage.addPower(distributed) + if (entity.powerStorage.isFull()) iterator.remove() -private fun getRemainingCapacity(destinations: List): Int { - return destinations.sumOf { it.powerStorage.getRemainingCapacity() } -} - -private fun completeChain(path: Array?, transferred: Int) { - path?.forEach { if (it.type is PowerFlowMeter) it.type.onCompleteChain(transferred) } -} - -// I hate this function but it works -fun getSorted(pathResistance: Array): IntArray { - // Store the shuffled indicies - val ranks = IntArray(pathResistance.size) { it } - val tempSorted = pathResistance.clone() - - for (index in ranks.indices) { - for (j in 0..< ranks.lastIndex) { - if ((tempSorted[j] ?: Double.MAX_VALUE) > (tempSorted[j + 1] ?: Double.MAX_VALUE)) { - val temp = tempSorted[j] - tempSorted[j] = tempSorted[j + 1] - tempSorted[j + 1] = temp - - val prev = ranks[j] - ranks[j] = prev + 1 - ranks[j + 1] = prev + remainingPower -= (distributed - r) } } - } - return ranks + return remainingPower + } } - -val stupidOffsets: Array = arrayOf( - // Upper ring - Vec3i(1, 1, 0), - Vec3i(-1, 1, 0), - Vec3i(0, 1, 1), - Vec3i(0, 1, -1), - // Lower ring - Vec3i(1, -1, 0), - Vec3i(-1, -1, 0), - Vec3i(0, -1, 1), - Vec3i(0, -1, -1), - - // Middle ring - Vec3i(2, 0, 0), - Vec3i(-2, 0, 0), - Vec3i(0, 0, -2), - Vec3i(0, 0, -2), - - Vec3i(1, 0, 1), - Vec3i(-1, 0, 1), - Vec3i(1, 0, -1), - Vec3i(-1, 0, -1), -) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index d186a8c047..121c1c80b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,10 +1,17 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ @@ -59,4 +66,82 @@ abstract class TransportCache(val holder: CacheHolder<*>) { } fun getRawCache() = cache + + /** + * Gets the powered entities accessible from this location, assuming it is an input + * This method is used in conjunction with input registration to allow direct access via signs, and remote access via registered inputs + **/ + fun getInputEntities(location: BlockKey): Set { + val inputManager = holder.getWorld().ion.inputManager + val registered = inputManager.getHolders(type, location) + + val adjacentBlocks = stupidOffsets.mapNotNull { MultiblockEntities.getMultiblockEntity(holder.getWorld(), it.x, it.y, it.z) } + + return registered.plus(adjacentBlocks) + } + + private val stupidOffsets: Array = arrayOf( + // Upper ring + Vec3i(1, 1, 0), + Vec3i(-1, 1, 0), + Vec3i(0, 1, 1), + Vec3i(0, 1, -1), + // Lower ring + Vec3i(1, -1, 0), + Vec3i(-1, -1, 0), + Vec3i(0, -1, 1), + Vec3i(0, -1, -1), + + // Middle ring + Vec3i(2, 0, 0), + Vec3i(-2, 0, 0), + Vec3i(0, 0, -2), + Vec3i(0, 0, -2), + + Vec3i(1, 0, 1), + Vec3i(-1, 0, 1), + Vec3i(1, 0, -1), + Vec3i(-1, 0, -1), + ) + + inline fun getExtractorSources(extractorLocation: BlockKey, filterNot: (T) -> Boolean): List { + val sources = mutableListOf() + + for (face in ADJACENT_BLOCK_FACES) { + val inputLocation = getRelative(extractorLocation, face) + if (holder.getOrCacheGlobalNode(inputLocation) !is PowerNode.PowerInputNode) continue + val entities = getInputEntities(inputLocation) + + for (entity in entities) { + if (entity !is T) continue + if (filterNot.invoke(entity)) continue + sources.add(entity) + } + } + + return sources + } +} + +// I hate this function but it works +fun getSorted(pathResistance: Array): IntArray { + // Store the shuffled indicies + val ranks = IntArray(pathResistance.size) { it } + val tempSorted = pathResistance.clone() + + for (index in ranks.indices) { + for (j in 0..< ranks.lastIndex) { + if ((tempSorted[j] ?: Double.MAX_VALUE) > (tempSorted[j + 1] ?: Double.MAX_VALUE)) { + val temp = tempSorted[j] + tempSorted[j] = tempSorted[j + 1] + tempSorted[j + 1] = temp + + val prev = ranks[j] + ranks[j] = prev + 1 + ranks[j + 1] = prev + } + } + } + + return ranks } From 77cf88f9c0cad6bd3df4059d38ab3d4f3337897c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 20 Nov 2024 12:03:54 -0600 Subject: [PATCH 316/500] actually save extractor data, more organization --- .../server/command/admin/IonChunkCommand.kt | 6 +-- .../transport/fluids/FluidRegistry.kt | 1 - .../extractors/ChunkExtractorManager.kt | 2 +- .../manager/extractors/ExtractorManager.kt | 2 +- .../nodes/cache/FluidTransportCache.kt | 3 +- .../nodes/cache/PowerTransportCache.kt | 3 +- .../transport/nodes/cache/TransportCache.kt | 37 ++++++++++++++++++- .../transport/util/NodePathfinding.kt | 26 ------------- .../server/features/world/chunk/IonChunk.kt | 1 + 9 files changed, 43 insertions(+), 38 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 9aaa83c6a9..0b7623cbde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -12,7 +12,6 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion @@ -147,8 +146,9 @@ object IonChunkCommand : SLCommand() { @Subcommand("test flood") fun onTestFloodFill(sender: Player, network: CacheType) { sender.information("Trying to find input nodes") - val (cached, location) = requireLookingAt(sender, network) - val destinations = getNetworkDestinations(CacheType.POWER, sender.world, location) { true } + val (_, location) = requireLookingAt(sender, network) + val cache = network.get(sender.chunk.ion()) + val destinations = cache.getNetworkDestinations(location) { true } sender.information("${destinations.size} destinations") sender.highlightBlocks(destinations.map(::toVec3i), 50L) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt index d5fc7730ea..a00c8e4445 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt @@ -10,7 +10,6 @@ import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.WHITE import java.util.concurrent.ConcurrentHashMap - object FluidRegistry : IonServerComponent() { private val fluids = mutableListOf() private val byIdentifier = ConcurrentHashMap() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index de1fbf11af..1e6b823a22 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -44,7 +44,7 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag extractors = existing.associateWithTo(Long2ObjectOpenHashMap()) { ExtractorData(it) } } - override fun onSave() { + override fun save() { pdc.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.keys.toLongArray()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index d37508bd41..86120e1c4e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -25,7 +25,7 @@ abstract class ExtractorManager { } open fun onLoad() {} - open fun onSave() {} + open fun save() {} class ExtractorData(val pos: BlockKey) { private var lastTicked = System.currentTimeMillis() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 3aacf5be17..542b2c252b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -12,7 +12,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getIdealPath -import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis @@ -51,7 +50,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa if (source.getStoredResources().isEmpty()) return@submit // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(type, world, location) { node -> + val destinations: List = getNetworkDestinations(location) { node -> world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 7796d99db2..1e4a3d3d9d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -11,7 +11,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.Power import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getIdealPath -import net.horizonsend.ion.server.features.transport.util.getNetworkDestinations import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -47,7 +46,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val source = sources.randomOrNull() ?: return@submit //TODO take from all // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(CacheType.POWER, world, location) { node -> + val destinations: List = getNetworkDestinations(location) { node -> world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 121c1c80b6..9dc9fcd676 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,12 +1,14 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -16,8 +18,10 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block +import org.bukkit.block.BlockFace abstract class TransportCache(val holder: CacheHolder<*>) { private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() @@ -39,8 +43,8 @@ abstract class TransportCache(val holder: CacheHolder<*>) { } fun getOrCache(location: BlockKey): Node? { - if (isCached(location)) return getCached(location) - else return cache(location, getBlockIfLoaded(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return null) + if (isCached(location)) return getCached(location).apply { println("Already cached, ${toVec3i(location)} $this") } + else return run { println("cache miss"); cache(location, getBlockIfLoaded(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return null) } } fun cache(location: BlockKey) { @@ -121,6 +125,35 @@ abstract class TransportCache(val holder: CacheHolder<*>) { return sources } + + inline fun getNetworkDestinations( + originPos: BlockKey, + check: (Node.NodePositionData) -> Boolean, + ): List { + val originNode = getOrCacheNode(type, holder.getWorld(), originPos) ?: return listOf() + + val visitQueue = ArrayDeque() + val visited = LongOpenHashSet() + val destinations = LongOpenHashSet() + + visitQueue.addAll(originNode.getNextNodes( + world = holder.getWorld(), + position = originPos, + backwards = BlockFace.SELF, + null + )) + + while (visitQueue.isNotEmpty()) { + val current = visitQueue.removeFirst() + visited.add(current.position) + + if (current.type is T && check(current)) destinations.add(current.position) + + visitQueue.addAll(current.getNextNodes(null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) + } + + return destinations.toList() + } } // I hate this function but it works diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index b05ee07d29..9214e4370f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -18,32 +18,6 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { return type.get(chunk).getOrCache(pos) } -inline fun getNetworkDestinations(cacheType: CacheType, world: World, originPos: BlockKey, check: (Node.NodePositionData) -> Boolean): List { - val originNode = getOrCacheNode(cacheType, world, originPos) ?: return listOf() - - val visitQueue = ArrayDeque() - val visited = LongOpenHashSet() - val destinations = LongOpenHashSet() - - visitQueue.addAll(originNode.getNextNodes( - world = world, - position = originPos, - backwards = BlockFace.SELF, - null - )) - - while (visitQueue.isNotEmpty()) { - val current = visitQueue.removeFirst() - visited.add(current.position) - - if (current.type is T && check(current)) destinations.add(current.position) - - visitQueue.addAll(current.getNextNodes(null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) - } - - return destinations.toList() -} - /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index a9f832a5e2..b81b7eeda9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -76,6 +76,7 @@ class IonChunk( **/ fun save() { multiblockManager.save() + transportNetwork.extractorManager.save() } /** From 428208bbdff205ac5e03cd5e66e3aa45e2deefbe Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 20 Nov 2024 12:16:19 -0600 Subject: [PATCH 317/500] rename gas fluids to gas to allow future liquid variants --- .../ion/server/features/gas/Gasses.kt | 16 ++++++------- .../type/fluid/ElectrolysisMultiblock.kt | 8 +++---- .../transport/fluids/FluidRegistry.kt | 23 +++++++++---------- .../transport/fluids/types/BasicPipedFluid.kt | 4 ---- .../transport/fluids/types/GasFluid.kt | 6 ++++- .../transport/fluids/types/SimpleFluid.kt | 7 ++++++ 6 files changed, 35 insertions(+), 29 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/SimpleFluid.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt index 54cbe5fee4..29b840de68 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt @@ -29,7 +29,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::hydrogen, - transportedFluidSupplier = Supplier { FluidRegistry.HYDROGEN } + transportedFluidSupplier = Supplier { FluidRegistry.HYDROGEN_GAS } ) {} ) val NITROGEN: GasFuel = registerGas( @@ -40,7 +40,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::nitrogen, - transportedFluidSupplier = { FluidRegistry.NITROGEN } + transportedFluidSupplier = { FluidRegistry.NITROGEN_GAS } ) {} ) val METHANE: GasFuel = registerGas( @@ -51,7 +51,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.methane.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.methane.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::methane, - transportedFluidSupplier = { FluidRegistry.METHANE } + transportedFluidSupplier = { FluidRegistry.METHANE_GAS } ) {} ) @@ -63,7 +63,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_OXYGEN", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.oxygen.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::oxygen, - transportedFluidSupplier = { FluidRegistry.OXYGEN } + transportedFluidSupplier = { FluidRegistry.OXYGEN_GAS } ) {} ) val CHLORINE: GasOxidizer = registerGas( @@ -73,7 +73,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_CHLORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.chlorine.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::chlorine, - transportedFluidSupplier = { FluidRegistry.CHLORINE } + transportedFluidSupplier = { FluidRegistry.CHLORINE_GAS } ) {} ) val FLUORINE: GasOxidizer = registerGas( @@ -83,7 +83,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_FLUORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.fluorine.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::fluorine, - transportedFluidSupplier = { FluidRegistry.FLUORINE } + transportedFluidSupplier = { FluidRegistry.FLUORINE_GAS } ) {} ) @@ -94,7 +94,7 @@ object Gasses : IonServerComponent(false) { displayName = text("Helium", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_HELIUM", configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::helium, - transportedFluidSupplier = { FluidRegistry.HELIUM } + transportedFluidSupplier = { FluidRegistry.HELIUM_GAS } ) {} ) val CARBON_DIOXIDE: Gas = registerGas(object : Gas( @@ -102,7 +102,7 @@ object Gasses : IonServerComponent(false) { displayName = text("Carbon Dioxide", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_CARBON_DIOXIDE", configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::carbonDioxide, - transportedFluidSupplier = { FluidRegistry.CARBON_DIOXIDE } + transportedFluidSupplier = { FluidRegistry.CARBON_DIOXIDE_GAS } ) {} ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 96b5e2e83d..0744754467 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -26,8 +26,8 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs -import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.HYDROGEN -import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.OXYGEN +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.HYDROGEN_GAS +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.OXYGEN_GAS import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.WATER import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 @@ -214,8 +214,8 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf( loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER, inputAllowed = true, extractionAllowed = false)), - loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN, inputAllowed = false, extractionAllowed = true)), - loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN, inputAllowed = false, extractionAllowed = true)) + loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN_GAS, inputAllowed = false, extractionAllowed = true)), + loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN_GAS, inputAllowed = false, extractionAllowed = true)) ) private val hydrogenStorage by lazy { getNamedStorage("hydrogen_tank") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt index a00c8e4445..ecaeaea031 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory import net.horizonsend.ion.server.features.transport.fluids.types.GasFluid +import net.horizonsend.ion.server.features.transport.fluids.types.SimpleFluid import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE @@ -19,18 +20,16 @@ object FluidRegistry : IonServerComponent() { override val categories: Array = arrayOf() }) - val HYDROGEN = register(GasFluid("HYDROGEN") { Gasses.HYDROGEN }) - val NITROGEN = register(GasFluid("NITROGEN") { Gasses.NITROGEN }) - val METHANE = register(GasFluid("METHANE") { Gasses.METHANE }) - val OXYGEN = register(GasFluid("OXYGEN") { Gasses.OXYGEN }) - val CHLORINE = register(GasFluid("CHLORINE") { Gasses.CHLORINE }) - val FLUORINE = register(GasFluid("FLUORINE") { Gasses.FLUORINE }) - val HELIUM = register(GasFluid("FLUORINE") { Gasses.FLUORINE }) - val CARBON_DIOXIDE = register(GasFluid("FLUORINE") { Gasses.FLUORINE }) - val WATER = register(object : Fluid("WATER") { - override val displayName: Component = text("Water", BLUE) - override val categories: Array = arrayOf() - }) + val HYDROGEN_GAS = register(GasFluid("HYDROGEN_GAS") { Gasses.HYDROGEN }) + val NITROGEN_GAS = register(GasFluid("NITROGEN_GAS") { Gasses.NITROGEN }) + val METHANE_GAS = register(GasFluid("METHANE_GAS") { Gasses.METHANE }) + val OXYGEN_GAS = register(GasFluid("OXYGEN_GAS") { Gasses.OXYGEN }) + val CHLORINE_GAS = register(GasFluid("CHLORINE_GAS") { Gasses.CHLORINE }) + val FLUORINE_GAS = register(GasFluid("FLUORINE_GAS") { Gasses.FLUORINE }) + val HELIUM_GAS = register(GasFluid("HELIUM_GAS") { Gasses.HELIUM }) + val CARBON_DIOXIDE_GAS = register(GasFluid("CARBON_DIOXIDE_GAS") { Gasses.CARBON_DIOXIDE }) + + val WATER = register(SimpleFluid("WATER", text("Water", BLUE), arrayOf())) init { fluids.associateByTo(byIdentifier) { it.identifier } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt deleted file mode 100644 index 0b562773af..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/BasicPipedFluid.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.transport.fluids.types - -class BasicPipedFluid /*: Fluid()*/ { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt index dcf228f051..40ce510d10 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/GasFluid.kt @@ -1,9 +1,12 @@ package net.horizonsend.ion.server.features.transport.fluids.types +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.gas.type.Gas import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GRAY import java.util.function.Supplier class GasFluid( @@ -12,6 +15,7 @@ class GasFluid( ) : Fluid(identifier) { override val categories: Array = arrayOf(FluidCategory.GAS) - override val displayName: Component get() = gas.displayName + override val displayName: Component get() = ofChildren(gas.displayName, text(" Gas", GRAY)) + val gas get() = gasSupplier.get() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/SimpleFluid.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/SimpleFluid.kt new file mode 100644 index 0000000000..e247816759 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/types/SimpleFluid.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.transport.fluids.types + +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.properties.FluidCategory +import net.kyori.adventure.text.Component + +class SimpleFluid(identifier: String, override val displayName: Component, override val categories: Array) : Fluid(identifier) From 6b0ddf61f9ee783967ac2abf6d87e60e3979a307 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 20 Nov 2024 12:58:04 -0600 Subject: [PATCH 318/500] name them low pressure too --- .../ion/server/features/gas/Gasses.kt | 16 ++++++++-------- .../type/fluid/ElectrolysisMultiblock.kt | 8 ++++---- .../features/transport/fluids/FluidRegistry.kt | 16 ++++++++-------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt index 29b840de68..b408cca0df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gas/Gasses.kt @@ -29,7 +29,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.hydrogen.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::hydrogen, - transportedFluidSupplier = Supplier { FluidRegistry.HYDROGEN_GAS } + transportedFluidSupplier = Supplier { FluidRegistry.LOW_PRESSURE_HYDROGEN_GAS } ) {} ) val NITROGEN: GasFuel = registerGas( @@ -40,7 +40,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.nitrogen.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::nitrogen, - transportedFluidSupplier = { FluidRegistry.NITROGEN_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_NITROGEN_GAS } ) {} ) val METHANE: GasFuel = registerGas( @@ -51,7 +51,7 @@ object Gasses : IonServerComponent(false) { powerPerUnit = ConfigurationFiles.globalGassesConfiguration().gasses.methane.powerPerUnit, cooldown = ConfigurationFiles.globalGassesConfiguration().gasses.methane.cooldown, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::methane, - transportedFluidSupplier = { FluidRegistry.METHANE_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_METHANE_GAS } ) {} ) @@ -63,7 +63,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_OXYGEN", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.oxygen.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::oxygen, - transportedFluidSupplier = { FluidRegistry.OXYGEN_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_OXYGEN_GAS } ) {} ) val CHLORINE: GasOxidizer = registerGas( @@ -73,7 +73,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_CHLORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.chlorine.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::chlorine, - transportedFluidSupplier = { FluidRegistry.CHLORINE_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_CHLORINE_GAS } ) {} ) val FLUORINE: GasOxidizer = registerGas( @@ -83,7 +83,7 @@ object Gasses : IonServerComponent(false) { containerIdentifier = "GAS_CANISTER_FLUORINE", powerMultiplier = ConfigurationFiles.globalGassesConfiguration().gasses.fluorine.powerMultiplier, configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::fluorine, - transportedFluidSupplier = { FluidRegistry.FLUORINE_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_FLUORINE_GAS } ) {} ) @@ -94,7 +94,7 @@ object Gasses : IonServerComponent(false) { displayName = text("Helium", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_HELIUM", configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::helium, - transportedFluidSupplier = { FluidRegistry.HELIUM_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_HELIUM_GAS } ) {} ) val CARBON_DIOXIDE: Gas = registerGas(object : Gas( @@ -102,7 +102,7 @@ object Gasses : IonServerComponent(false) { displayName = text("Carbon Dioxide", NamedTextColor.BLUE), containerIdentifier = "GAS_CANISTER_CARBON_DIOXIDE", configurationSupplier = ConfigurationFiles.globalGassesConfiguration().gasses::carbonDioxide, - transportedFluidSupplier = { FluidRegistry.CARBON_DIOXIDE_GAS } + transportedFluidSupplier = { FluidRegistry.LOW_PRESSURE_CARBON_DIOXIDE_GAS } ) {} ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 0744754467..5f4066c82f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -26,8 +26,8 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.pane import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset.stairs -import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.HYDROGEN_GAS -import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.OXYGEN_GAS +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.LOW_PRESSURE_HYDROGEN_GAS +import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.LOW_PRESSURE_OXYGEN_GAS import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry.WATER import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 @@ -214,8 +214,8 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf( loadStoredResource(data, "water_tank", text("Water Tank"), TANK_1, SingleFluidStorage(1000, WATER, inputAllowed = true, extractionAllowed = false)), - loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, OXYGEN_GAS, inputAllowed = false, extractionAllowed = true)), - loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, HYDROGEN_GAS, inputAllowed = false, extractionAllowed = true)) + loadStoredResource(data, "oxygen_tank", text("Oxygen Tank"), TANK_2, SingleFluidStorage(10000, LOW_PRESSURE_OXYGEN_GAS, inputAllowed = false, extractionAllowed = true)), + loadStoredResource(data, "hydrogen_tank", text("Hydrogen Tank"), TANK_3, SingleFluidStorage(10000, LOW_PRESSURE_HYDROGEN_GAS, inputAllowed = false, extractionAllowed = true)) ) private val hydrogenStorage by lazy { getNamedStorage("hydrogen_tank") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt index ecaeaea031..3ce782dc94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidRegistry.kt @@ -20,14 +20,14 @@ object FluidRegistry : IonServerComponent() { override val categories: Array = arrayOf() }) - val HYDROGEN_GAS = register(GasFluid("HYDROGEN_GAS") { Gasses.HYDROGEN }) - val NITROGEN_GAS = register(GasFluid("NITROGEN_GAS") { Gasses.NITROGEN }) - val METHANE_GAS = register(GasFluid("METHANE_GAS") { Gasses.METHANE }) - val OXYGEN_GAS = register(GasFluid("OXYGEN_GAS") { Gasses.OXYGEN }) - val CHLORINE_GAS = register(GasFluid("CHLORINE_GAS") { Gasses.CHLORINE }) - val FLUORINE_GAS = register(GasFluid("FLUORINE_GAS") { Gasses.FLUORINE }) - val HELIUM_GAS = register(GasFluid("HELIUM_GAS") { Gasses.HELIUM }) - val CARBON_DIOXIDE_GAS = register(GasFluid("CARBON_DIOXIDE_GAS") { Gasses.CARBON_DIOXIDE }) + val LOW_PRESSURE_HYDROGEN_GAS = register(GasFluid("LOW_PRESSURE_HYDROGEN_GAS") { Gasses.HYDROGEN }) + val LOW_PRESSURE_NITROGEN_GAS = register(GasFluid("LOW_PRESSURE_NITROGEN_GAS") { Gasses.NITROGEN }) + val LOW_PRESSURE_METHANE_GAS = register(GasFluid("LOW_PRESSURE_METHANE_GAS") { Gasses.METHANE }) + val LOW_PRESSURE_OXYGEN_GAS = register(GasFluid("LOW_PRESSURE_OXYGEN_GAS") { Gasses.OXYGEN }) + val LOW_PRESSURE_CHLORINE_GAS = register(GasFluid("LOW_PRESSURE_CHLORINE_GAS") { Gasses.CHLORINE }) + val LOW_PRESSURE_FLUORINE_GAS = register(GasFluid("LOW_PRESSURE_FLUORINE_GAS") { Gasses.FLUORINE }) + val LOW_PRESSURE_HELIUM_GAS = register(GasFluid("LOW_PRESSURE_HELIUM_GAS") { Gasses.HELIUM }) + val LOW_PRESSURE_CARBON_DIOXIDE_GAS = register(GasFluid("LOW_PRESSURE_CARBON_DIOXIDE_GAS") { Gasses.CARBON_DIOXIDE }) val WATER = register(SimpleFluid("WATER", text("Water", BLUE), arrayOf())) From 34fd61e470e1971b19422bab77442d9168a86be9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 22 Nov 2024 18:15:46 -0600 Subject: [PATCH 319/500] Multiblock linkage system --- .../multiblock/entity/MultiblockEntity.kt | 45 +++++++++++++- .../entity/linkages/LinkageHolder.kt | 62 +++++++++++++++++++ .../entity/linkages/MultiblockLinkage.kt | 31 ++++++++++ .../entity/linkages/MultiblockLinkages.kt | 41 ++++++++++++ .../entity/linkages/ShipLinkageManager.kt | 37 +++++++++++ .../entity/linkages/WorldLinkageManager.kt | 5 ++ .../manager/ChunkMultiblockManager.kt | 2 + .../multiblock/manager/MultiblockManager.kt | 11 ++-- .../manager/ShipMultiblockManager.kt | 24 ++++--- .../manager/WorldMultiblockManager.kt | 2 + .../starship/movement/RotationMovement.kt | 17 +++++ .../starship/movement/StarshipMovement.kt | 4 +- .../starship/movement/TranslateMovement.kt | 13 ++++ .../transport/nodes/inputs/InputManager.kt | 2 - 14 files changed, 278 insertions(+), 18 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/LinkageHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/WorldLinkageManager.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 92265fed32..39435c0cc4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkage import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement @@ -9,6 +10,7 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -23,6 +25,9 @@ import org.bukkit.block.Sign import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder import org.bukkit.persistence.PersistentDataAdapterContext +import java.util.UUID +import java.util.function.Supplier +import kotlin.reflect.KClass /** * @param manager The multiblock manager that this is registered to @@ -76,8 +81,16 @@ abstract class MultiblockEntity( val locationKey = toBlockKey(x, y, z) + fun processRemoval() { + removed = true + + handleRemoval() + if (this is DisplayMultiblockEntity) displayHandler.remove() + removeLinkages() + } + /** Logic to be run upon the removal of this entity */ - open fun handleRemoval() {} + protected open fun handleRemoval() {} /** Removes this multiblock entity */ fun remove() { @@ -87,8 +100,13 @@ abstract class MultiblockEntity( /** Logic to be run upon the unloading of the chunk holding this entity */ open fun onUnload() {} + fun processLoad() { + if (this is DisplayMultiblockEntity) displayHandler.update() + onLoad() + } + /** Logic to be run upon the loading of the chunk holding this entity, or its creation */ - open fun onLoad() {} + protected open fun onLoad() {} open fun displaceAdditional(movement: StarshipMovement) {} @@ -286,6 +304,7 @@ abstract class MultiblockEntity( manager.markChanged() } + // Section inputs fun registerInputs(type: CacheType, locations: Set) { val inputManager = manager.getInputManager() for (location in locations) { @@ -299,4 +318,26 @@ abstract class MultiblockEntity( inputManager.deRegisterInput(type, toBlockKey(location), this) } } + + val linkages = mutableMapOf() + + protected fun registerLinkage(right: Int, up: Int, forward: Int, linkageDirection: RelativeFace, allowedEntities: Array>): Supplier { + val realLocKey = toBlockKey(getPosRelative(right, up, forward)) + val new = MultiblockLinkage(this, allowedEntities, realLocKey, linkageDirection[structureDirection]) + + val id = UUID.randomUUID() + + linkages[id] = (realLocKey) + manager.getLinkageManager().registerLinkage(realLocKey, new) + + return Supplier { + val currentPos = linkages[id] ?: return@Supplier null + val linkage = manager.getLinkageManager().getLinkages(currentPos).firstOrNull() { it.owner == this } + linkage?.getOtherEnd(manager.getLinkageManager()) + } + } + + private fun removeLinkages() { + for (blockKey in linkages.values) manager.getLinkageManager().deRegisterLinkage(blockKey) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/LinkageHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/LinkageHolder.kt new file mode 100644 index 0000000000..228cf2a264 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/LinkageHolder.kt @@ -0,0 +1,62 @@ +package net.horizonsend.ion.server.features.multiblock.entity.linkages + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement + +sealed interface LinkageHolder { + fun contains(holder: MultiblockEntity): Boolean + fun getOwners(): Set + fun getLinkages(): Set + + fun displace(movement: StarshipMovement) +} + +data class SingleMultiblockLinkage(val linkage: MultiblockLinkage) : LinkageHolder { + override fun contains(holder: MultiblockEntity): Boolean { + return this.linkage.owner == holder + } + + override fun getOwners(): Set = setOf(linkage.owner) + override fun getLinkages(): Set = setOf(linkage) + + override fun displace(movement: StarshipMovement) = linkage.displace(movement) +} + +class SharedMultiblockLinkage : LinkageHolder { + private val linkages: ObjectOpenHashSet = ObjectOpenHashSet() + + override fun contains(holder: MultiblockEntity): Boolean { + return linkages.any { it.owner == holder } + } + + override fun getOwners(): Set { + return linkages.mapTo(mutableSetOf()) { it.owner } + } + + override fun getLinkages(): Set { + return linkages + } + + fun add(multiblockEntity: MultiblockLinkage) { + linkages.add(multiblockEntity) + } + + fun remove(multiblockEntity: MultiblockLinkage) { + linkages.remove(multiblockEntity) + } + + fun getAllHolders() = linkages.clone() + + override fun displace(movement: StarshipMovement) { + return linkages.forEach { it.displace(movement) } + } + + companion object { + fun of(vararg entities: MultiblockLinkage): SharedMultiblockLinkage { + val new = SharedMultiblockLinkage() + entities.forEach(new::add) + return new + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt new file mode 100644 index 0000000000..3ad766bce7 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt @@ -0,0 +1,31 @@ +package net.horizonsend.ion.server.features.multiblock.entity.linkages + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import org.bukkit.block.BlockFace +import kotlin.reflect.KClass + +open class MultiblockLinkage( + val owner: MultiblockEntity, + val allowedLinkages: Array>, + private var location: BlockKey, + private var linkDirection: BlockFace +) { + fun getLinkLocation(): BlockKey = getRelative(location, linkDirection) + + fun displace(movement: StarshipMovement) { + location = movement.displaceKey(location) + linkDirection = movement.displaceFace(linkDirection) + } + + open fun canLink(to: MultiblockEntity): Boolean { + return allowedLinkages.any { it.isInstance(to) } + } + + fun getOtherEnd(manager: MultiblockLinkageManager): MultiblockEntity? { + val linkages = manager.getLinkages(getLinkLocation()) + return linkages.firstOrNull { canLink(it.owner) }?.owner + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt new file mode 100644 index 0000000000..49d225e749 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt @@ -0,0 +1,41 @@ +package net.horizonsend.ion.server.features.multiblock.entity.linkages + +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import java.util.concurrent.ConcurrentHashMap + +abstract class MultiblockLinkageManager { + protected open val linkages = ConcurrentHashMap() + + fun registerLinkage(location: BlockKey, linkage: MultiblockLinkage) { + when (val present: LinkageHolder? = linkages[location]) { + is SingleMultiblockLinkage -> linkages[location] = SharedMultiblockLinkage.of(present.linkage, linkage) + is SharedMultiblockLinkage -> present.add(linkage) + null -> linkages[location] = SingleMultiblockLinkage(linkage) + } + } + + fun deRegisterLinkage(location: BlockKey) { + linkages.remove(location) + } + + fun getLinkages(location: BlockKey): Set { + return linkages[location]?.getLinkages() ?: setOf() + } + + fun transferTo(other: MultiblockLinkageManager) { + for ((key, holder) in linkages) { + val linkages = holder.getLinkages() + for (linkage in linkages) other.registerLinkage(key, linkage) + } + } + + fun transferTo(keys: Iterable, other: MultiblockLinkageManager) { + val intersect = linkages.keys.intersect(keys.toSet()) + + for (key in intersect) { + val holder = linkages[key] ?: continue + val linkages = holder.getLinkages() + for (linkage in linkages) other.registerLinkage(key, linkage) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt new file mode 100644 index 0000000000..5bdf0ad114 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt @@ -0,0 +1,37 @@ +package net.horizonsend.ion.server.features.multiblock.entity.linkages + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.features.multiblock.manager.ShipMultiblockManager +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import java.util.concurrent.ConcurrentHashMap + +class ShipLinkageManager(private val shipMultiblockManager: ShipMultiblockManager) : MultiblockLinkageManager() { + fun pilot() { + val old = shipMultiblockManager.world.ion.multiblockManager.linkageManager + val newKeys = shipMultiblockManager.starship.blocks.mapTo(LongOpenHashSet()) { toBlockKey(blockKeyX(it), blockKeyY(it), blockKeyZ(it)) } + old.transferTo(newKeys, this) + } + + fun release() { + transferTo(shipMultiblockManager.world.ion.multiblockManager.linkageManager) + } + + override var linkages: ConcurrentHashMap = ConcurrentHashMap() + + fun displace(movement: StarshipMovement) { + val new: ConcurrentHashMap = ConcurrentHashMap() + + for ((key, holder) in linkages) { + holder.displace(movement) + new[movement.displaceKey(key)] = holder + } + + linkages = new + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/WorldLinkageManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/WorldLinkageManager.kt new file mode 100644 index 0000000000..831680bb2a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/WorldLinkageManager.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.multiblock.entity.linkages + +import net.horizonsend.ion.server.features.world.IonWorld + +class WorldLinkageManager(val world: IonWorld) : MultiblockLinkageManager() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 600713b19c..a60bdfe44f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkageManager import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache @@ -20,6 +21,7 @@ import org.slf4j.Logger class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManager(log) { override val world: World = chunk.world override fun getInputManager(): InputManager = chunk.region.world.inputManager + override fun getLinkageManager(): MultiblockLinkageManager = chunk.region.world.multiblockManager.linkageManager /** * Logic upon the chunk being saved diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index bf59ca423b..4a998540e9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkageManager import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock @@ -31,6 +31,8 @@ abstract class MultiblockManager(val log: Logger) { abstract fun getInputManager(): InputManager + abstract fun getLinkageManager(): MultiblockLinkageManager + abstract fun save() abstract fun markChanged() @@ -49,8 +51,7 @@ abstract class MultiblockManager(val log: Logger) { fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true) { multiblockEntities[entity.locationKey] = entity - entity.onLoad() - if (entity is DisplayMultiblockEntity) entity.displayHandler.update() + entity.processLoad() if (entity is SyncTickingMultiblockEntity) { syncTickingMultiblockEntities[entity.locationKey] = entity @@ -70,13 +71,11 @@ abstract class MultiblockManager(val log: Logger) { val key = toBlockKey(x, y, z) val entity = multiblockEntities.remove(key) - entity?.removed = true syncTickingMultiblockEntities.remove(key) asyncTickingMultiblockEntities.remove(key) - entity?.handleRemoval() - if (this is DisplayMultiblockEntity) this.displayHandler.remove() + entity?.processRemoval() return entity } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 03f805fea5..eef4e12acc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -6,6 +6,8 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkageManager +import net.horizonsend.ion.server.features.multiblock.entity.linkages.ShipLinkageManager import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity @@ -29,6 +31,7 @@ import org.bukkit.block.Sign import java.util.concurrent.ConcurrentHashMap class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServer.slF4JLogger) { + private val multiblockLinkageManager = ShipLinkageManager(this) override var multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() /** All the ticked multiblock entities of this chunk */ @@ -41,6 +44,10 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe return starship.transportManager.getInputProvider() } + override fun getLinkageManager(): MultiblockLinkageManager { + return multiblockLinkageManager + } + override fun save() {} override fun getSignUnsavedTime(): Long = 0 override fun markChanged() {} @@ -50,12 +57,13 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe } init { - loadEntities() - MultiblockTicking.registerMultiblockManager(this) + loadEntities() tryFixEntities() + multiblockLinkageManager.pilot() + MultiblockTicking.registerMultiblockManager(this) } - fun loadEntities() { + private fun loadEntities() { val worldManager = world.ion.multiblockManager starship.iterateBlocks { x, y, z -> @@ -93,7 +101,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe // If it was lost, don't place it back if (!multiblockEntity.isIntact(checkSign = true)) { - multiblockEntity.handleRemoval() + multiblockEntity.processRemoval() continue } @@ -106,7 +114,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe // If it was lost, don't place it back if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { - multiblockEntity.handleRemoval() + multiblockEntity.processRemoval() continue } @@ -118,7 +126,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe // If it was lost, don't place it back if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { - multiblockEntity.handleRemoval() + multiblockEntity.processRemoval() continue } @@ -138,7 +146,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe ) } - fun displaceEntities(movement: StarshipMovement) { + fun displace(movement: StarshipMovement) { val newEntities = ConcurrentHashMap() for (entry in multiblockEntities) { @@ -165,6 +173,8 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe } asyncTickingMultiblockEntities = newAsyncTicking + + multiblockLinkageManager.displace(movement) } /** Mostly to be used with blueprint load or loadship, loads entities from their sign data */ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt index 9bd95653d2..702b3c72a8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.linkages.WorldLinkageManager import net.horizonsend.ion.server.features.world.IonWorld import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -13,6 +14,7 @@ import kotlin.reflect.KClass /** Contains multiblocks that need to be stored at a world level, such as base shields, mob defenders, etc. */ class WorldMultiblockManager(val world: IonWorld) { + val linkageManager = WorldLinkageManager(world) private val worldMultiblocks: ConcurrentHashMap, LinkedBlockingQueue> = ConcurrentHashMap() fun register(multiblockEntity: MultiblockEntity): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt index c6c26355e1..010dc540c9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/RotationMovement.kt @@ -6,6 +6,11 @@ import net.horizonsend.ion.server.features.starship.active.ActiveControlledStars import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.thruster.ThrustData +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.minecraft.world.level.block.Rotation import net.minecraft.world.level.block.state.BlockState import org.bukkit.Location @@ -106,6 +111,18 @@ class RotationMovement(starship: ActiveStarship, val clockwise: Boolean) : Stars return if (clockwise) vector.clone().rotateAroundY(0.5 * PI) else vector.clone().rotateAroundY(-0.5 * PI) } + override fun displaceKey(key: BlockKey): BlockKey { + val oldX = getX(key) + val oldY = getY(key) + val oldZ = getZ(key) + + return toBlockKey( + displaceX(oldX, oldZ), + displaceY(oldY), + displaceZ(oldZ, oldX) + ) + } + override fun onComplete() { starship.calculateHitbox() for (subsystem in starship.subsystems) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt index 79eb398e3b..cf71b2f287 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt @@ -24,6 +24,7 @@ import net.horizonsend.ion.server.features.starship.isFlyable import net.horizonsend.ion.server.features.starship.subsystem.misc.CryopodSubsystem import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.listener.misc.ProtectionListener +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX @@ -54,6 +55,7 @@ abstract class StarshipMovement(val starship: ActiveStarship, val newWorld: Worl abstract fun displaceLocation(oldLocation: Location): Location abstract fun displaceFace(face: BlockFace): BlockFace abstract fun displaceVector(vector: Vector): Vector + abstract fun displaceKey(key: BlockKey): BlockKey protected abstract fun movePassenger(passenger: Entity) protected abstract fun onComplete() protected abstract fun blockDataTransform(blockData: BlockState): BlockState @@ -136,7 +138,7 @@ abstract class StarshipMovement(val starship: ActiveStarship, val newWorld: Worl starship.calculateMinMax() updateCenter() updateSubsystems(world2) - starship.multiblockManager.displaceEntities(this) + starship.multiblockManager.displace(this) onComplete() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt index f958d2ae20..2338756015 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/TranslateMovement.kt @@ -3,7 +3,12 @@ package net.horizonsend.ion.server.features.starship.movement import io.papermc.paper.entity.TeleportFlag import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.add +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.world.entity.Relative import net.minecraft.world.level.block.state.BlockState @@ -84,6 +89,14 @@ class TranslateMovement(starship: ActiveStarship, val dx: Int, val dy: Int, val .clone() .add(Vector(dx.toDouble(), dy.toDouble(), dz.toDouble())) + override fun displaceKey(key: BlockKey): BlockKey { + return toBlockKey( + getX(key) + dx, + getY(key) + dy, + getZ(key) + dz, + ) + } + override fun displaceLocation(oldLocation: Location): Location { val newLocation = oldLocation.clone().add(dx, dy, dz) if (newWorld != null) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt index f170ff3869..2ce0c81da1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputManager.kt @@ -44,8 +44,6 @@ abstract class InputManager { is SharedMultiblockInput -> present.add(holder) null -> inputLocations[location] = SingleMultiblockInput(holder) } - - return } fun remove(location: BlockKey, holder: MultiblockEntity) { From 46bdcf29088c950f024a709548bb4055a8b4e5a6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 22 Nov 2024 18:38:27 -0600 Subject: [PATCH 320/500] Adjust ElectrolysisMultiblock shape --- .../entity/linkages/MultiblockLinkage.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 60 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt index 3ad766bce7..728e831582 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt @@ -26,6 +26,6 @@ open class MultiblockLinkage( fun getOtherEnd(manager: MultiblockLinkageManager): MultiblockEntity? { val linkages = manager.getLinkages(getLinkLocation()) - return linkages.firstOrNull { canLink(it.owner) }?.owner + return linkages.firstOrNull { canLink(it.owner) && it.linkDirection == linkDirection.oppositeFace }?.owner } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 5f4066c82f..9b83ea97e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -68,19 +68,12 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf() + override val fluidInputOffsets: Array = arrayOf(Vec3i(-2, -1, 1), Vec3i(+2, -1, 1)) override val powerInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) override val powerStorage: PowerStorage = loadStoredPower(data) @@ -258,7 +258,7 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock Date: Fri, 22 Nov 2024 18:41:19 -0600 Subject: [PATCH 321/500] Remove printlns --- .../server/features/transport/nodes/cache/TransportCache.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 9dc9fcd676..26b507b047 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -18,7 +18,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block import org.bukkit.block.BlockFace @@ -43,8 +42,8 @@ abstract class TransportCache(val holder: CacheHolder<*>) { } fun getOrCache(location: BlockKey): Node? { - if (isCached(location)) return getCached(location).apply { println("Already cached, ${toVec3i(location)} $this") } - else return run { println("cache miss"); cache(location, getBlockIfLoaded(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return null) } + if (isCached(location)) return getCached(location) + else return cache(location, getBlockIfLoaded(holder.getWorld(), getX(location), getY(location), getZ(location)) ?: return null) } fun cache(location: BlockKey) { From 13f817b0bb65770adaff6a9c01515c6fea734c88 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 23 Nov 2024 13:12:04 -0600 Subject: [PATCH 322/500] Clean up old namespaced keys --- .../custom/items/misc/MultimeterItem.kt | 10 ++--- .../type/UserManagedMultiblockEntity.kt | 8 ++-- .../persistence/NamespacedKeys.kt | 39 +++++++------------ 3 files changed, 23 insertions(+), 34 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 3f54554918..458e8c90d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.transport.util.getHeuristic import net.horizonsend.ion.server.features.transport.util.getNeighbors import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_VARIANT +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -86,7 +86,7 @@ object MultimeterItem : CustomItem("MULTIMETER") { val firstChunk = IonChunk[world, getX(firstPoint).shr(4), getZ(firstPoint).shr(4)] ?: return val secondPoint = itemStack.itemMeta.persistentDataContainer.get(Z, LONG) ?: return - val networkTypeIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) + val networkTypeIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_TYPE, INTEGER, 0) val cacheType = CacheType.entries[networkTypeIndex] val firstNode = cacheType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") @@ -97,10 +97,10 @@ object MultimeterItem : CustomItem("MULTIMETER") { } private fun cycleNetworks(audience: Audience, world: World, itemStack: ItemStack) { - val currentIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_VARIANT, INTEGER, 0) + val currentIndex = itemStack.itemMeta.persistentDataContainer.getOrDefault(NODE_TYPE, INTEGER, 0) val newIndex = (currentIndex + 1) % CacheType.entries.size itemStack.updateMeta { - it.persistentDataContainer.set(NODE_VARIANT, INTEGER, newIndex) + it.persistentDataContainer.set(NODE_TYPE, INTEGER, newIndex) } audience.success("Set network type to ${CacheType.entries[newIndex]}") @@ -153,7 +153,7 @@ object MultimeterItem : CustomItem("MULTIMETER") { if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { - audience.information("new neighbor: ${newNeighbor} at ${toVec3i(newNeighbor.node.position)}") + audience.information("new neighbor: $newNeighbor at ${toVec3i(newNeighbor.node.position)}") if (visited.contains(newNeighbor.node.position)) { audience.information("conmtinue") continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt index f02810fad4..42c3c5807d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/UserManagedMultiblockEntity.kt @@ -15,8 +15,8 @@ interface UserManagedMultiblockEntity { * Holds information about who is currently using this multiblock. **/ class UserManager(data: PersistentMultiblockData, private val persistent: Boolean) { - private var user: UUID? = data.getAdditionalData(NamespacedKeys.DRILL_USER, UuidDataType()) - private var userName: String? = data.getAdditionalData(NamespacedKeys.DRILL_USER_NAME, STRING) + private var user: UUID? = data.getAdditionalData(NamespacedKeys.USER, UuidDataType()) + private var userName: String? = data.getAdditionalData(NamespacedKeys.USER_NAME, STRING) fun clear() { user = null @@ -42,8 +42,8 @@ interface UserManagedMultiblockEntity { fun saveUserData(store: PersistentMultiblockData) { if (!persistent) return - user?.let { store.addAdditionalData(NamespacedKeys.DRILL_USER, UuidDataType(), it) } - userName?.let { store.addAdditionalData(NamespacedKeys.DRILL_USER_NAME, STRING, it) } + user?.let { store.addAdditionalData(NamespacedKeys.USER, UuidDataType(), it) } + userName?.let { store.addAdditionalData(NamespacedKeys.USER_NAME, STRING, it) } } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 6c0cfd1358..f1e5adf56c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -10,6 +10,8 @@ object NamespacedKeys { val Y = key("y") val Z = key("z") + val AXIS = key("axis") + val UP_DOWN = key("up_down") val LEFT_RIGHT = key("left_right") val FORWARD_BACKWARD = key("left_right") @@ -18,6 +20,9 @@ object NamespacedKeys { val BLOCK_STATE = key("block_state") val BLOCK_ENTITY = key("block_entity") + val TUBE_BUTTONS = key("tube_buttons") + val MATERIAL = key("material") + // Encounters PDC val ENCOUNTER = key("encounter") @@ -51,21 +56,11 @@ object NamespacedKeys { val CUSTOM_ENTITY = key("custom_entity") val SPLITTER_DIRECTION = key("splitter_direction") - val DRILL_USER = key("drill_user") - val DRILL_USER_NAME = key("drill_user_name") + val USER = key("user") + val USER_NAME = key("user") @Deprecated("") val ORE_CHECK = key("oreCheck") - val POWER = key("power") - val GAS = key("Gas") - - val POWER_TRANSPORT = key("power_transport") - val FLUID_TRANSPORT = key("gas_transport") - val ITEM_TRANSPORT = key("item_transport") - - val TUBE_BUTTONS = key("tube_buttons") - val MATERIAL = key("material") - val PROGRESS = key("progress") val LAST_PROGRESS_TICK = key("last_progress_tick") val CUSTOM_ITEM_RESULT = key("custom_item_result") @@ -86,26 +81,20 @@ object NamespacedKeys { val FORBIDDEN_BLOCKS = key("forbidden_blocks") val CARGO_CRATE = key("cargo_crate") - val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") - val STORED_MULTIBLOCK_ENTITIES_OLD = key("stored_multiblock_entities_old") + val POWER = key("power") + val GAS = key("Gas") - val RESOURCE_CAPACITY_MAX = key("resource_capacity_max") - val RESOURCE_CAPACITY_MIN = key("resource_capacity_min") + val POWER_TRANSPORT = key("power_transport") + val FLUID_TRANSPORT = key("gas_transport") + val ITEM_TRANSPORT = key("item_transport") - val PROCESSING_PROGRESS = key("processing_progress") + val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") + val STORED_MULTIBLOCK_ENTITIES_OLD = key("stored_multiblock_entities_old") - val NODE_COVERED_POSITIONS = key("node_covered_positions") - val AXIS = key("axis") val EXTRACTORS = key("extractors") - val SOLAR_CELL_EXTRACTORS = key("solar_cell_extractors") - val SOLAR_CELL_DETECTORS = key("solar_cell_detectors") val NODE_TYPE = key("node_type") - val NODE_VARIANT = key("node_variant") - - val NODES = key("chunk_nodes") - // Fluid storage val FLUID = key("fluid") val FLUID_AMOUNT = key("fluid_amount") From 9b2a8072eb1c08a88133340f4069797a07564e73 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 11:21:54 -0600 Subject: [PATCH 323/500] Proper merge nodes --- .../server/features/transport/nodes/types/Node.kt | 4 +++- .../features/transport/nodes/types/PowerNode.kt | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt index 5444d0e1b1..d04c3d5cbe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt @@ -37,9 +37,11 @@ interface Node { nodes.add(NodePositionData(cached, world, getRelative(position, adjacentFace), adjacentFace)) } - return nodes + return filterPositionData(nodes, backwards) } + fun filterPositionData(nextNodes: List, backwards: BlockFace): List = nextNodes + data class NodePositionData(val type: Node, val world: World, val position: BlockKey, val offset: BlockFace) { fun getNextNodes(filter: ((Node, BlockFace) -> Boolean)?): List = type.getNextNodes(world, position, offset.oppositeFace, filter) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 500dabc3bd..00b0539a71 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -61,6 +61,12 @@ sealed interface PowerNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is SpongeNode override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is SpongeNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { + val forward = backwards.oppositeFace + nextNodes.firstOrNull { it.offset == forward }?.let { return listOf(it) } + return nextNodes + } } data object PowerInvertedMergeNode : PowerNode { @@ -68,6 +74,12 @@ sealed interface PowerNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is EndRodNode override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is EndRodNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { + val forward = backwards.oppositeFace + nextNodes.firstOrNull { it.offset == forward }?.let { return listOf(it) } + return nextNodes + } } data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { From 0a78dc892dbba0c1986d05dbbd9486015c31f143 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 11:42:23 -0600 Subject: [PATCH 324/500] Already move it to its own class --- .../features/custom/items/misc/Wrench.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt new file mode 100644 index 0000000000..70b4d8edfd --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -0,0 +1,42 @@ +package net.horizonsend.ion.server.features.custom.items.misc + +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.miscellaneous.utils.text.itemName +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component.text +import org.bukkit.Material +import org.bukkit.block.Sign +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack + +object Wrench : CustomItem("WRENCH") { + override fun constructItemStack(): ItemStack { + return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { + it.setCustomModelData(8000) + it.displayName(text("Wrench").itemName) + } + } + + override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + + } + + override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + if (livingEntity !is Player) return + val clickedBlock = event?.clickedBlock ?: return + val state = clickedBlock.state + + if (livingEntity.isSneaking && state is Sign) return tryPickUpMultiblock(livingEntity, state) + if (state is Sign) return tryEditFilter(livingEntity, state) + } + + private fun tryPickUpMultiblock(player: Player, sign: Sign) { + + } + + private fun tryEditFilter(player: Player, sign: Sign) { // State TBD + + } +} From 8396c1cf31b6a7f23541ea16f2acab5fe9b8de9a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 16:45:41 -0600 Subject: [PATCH 325/500] Add sign handling to prepackaged, ability to pick up multis with wrench --- .../features/custom/blocks/CustomBlocks.kt | 80 +++++---- .../custom/blocks/InteractableCustomBlock.kt | 9 +- .../custom/blocks/MultiblockWorkbench.kt | 3 +- .../custom/items/misc/PackagedMultiblock.kt | 23 ++- .../features/custom/items/misc/Wrench.kt | 6 + .../features/multiblock/MultiblockAccess.kt | 4 +- .../server/features/multiblock/PrePackaged.kt | 165 ++++++++++++++++-- .../multiblock/shape/BlockRequirement.kt | 6 +- .../multiblock/shape/MultiblockShape.kt | 26 +-- 9 files changed, 247 insertions(+), 75 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 120624f7a6..6f3b101f98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.custom.blocks import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import net.horizonsend.ion.server.features.custom.items.CustomBlockItem import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC @@ -36,167 +37,167 @@ object CustomBlocks { } } - val ALUMINUM_ORE = register(CustomBlock( + val ALUMINUM_ORE : CustomBlock = register(CustomBlock( identifier = "ALUMINUM_ORE", blockData = mushroomBlockData(setOf(NORTH, UP)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_ALUMINUM) ) - )) + ) { CustomItems.ALUMINUM_ORE }) - val ALUMINUM_BLOCK = register(CustomBlock( + val ALUMINUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "ALUMINUM_BLOCK", blockData = mushroomBlockData(setOf(SOUTH, UP, WEST)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ALUMINUM_BLOCK) ) - )) + ) { CustomItems.ALUMINUM_BLOCK }) - val RAW_ALUMINUM_BLOCK = register(CustomBlock( + val RAW_ALUMINUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "RAW_ALUMINUM_BLOCK", blockData = mushroomBlockData(setOf(NORTH)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_ALUMINUM_BLOCK) ) - )) + ) { CustomItems.RAW_ALUMINUM_BLOCK }) - val CHETHERITE_ORE = register(CustomBlock( + val CHETHERITE_ORE : CustomBlock = register(CustomBlock( identifier = "CHETHERITE_ORE", blockData = mushroomBlockData(setOf(EAST, NORTH, UP)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::CHETHERITE) ) - )) + ) { CustomItems.CHETHERITE_ORE }) - val STEEL_BLOCK = register(CustomBlock( + val STEEL_BLOCK : CustomBlock = register(CustomBlock( identifier = "STEEL_BLOCK", blockData = mushroomBlockData(setOf(SOUTH, UP, DOWN)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::STEEL_BLOCK) ) - )) + ) { CustomItems.STEEL_BLOCK }) - val CHETHERITE_BLOCK = register(CustomBlock( + val CHETHERITE_BLOCK : CustomBlock = register(CustomBlock( identifier = "CHETHERITE_BLOCK", blockData = mushroomBlockData(setOf(SOUTH, UP)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::CHETHERITE_BLOCK) ) - )) + ) { CustomItems.CHETHERITE_BLOCK }) - val TITANIUM_ORE = register(CustomBlock( + val TITANIUM_ORE : CustomBlock = register(CustomBlock( identifier = "TITANIUM_ORE", blockData = mushroomBlockData(setOf(UP, WEST)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_TITANIUM) ) - )) + ) { CustomItems.TITANIUM_ORE }) - val TITANIUM_BLOCK = register(CustomBlock( + val TITANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "TITANIUM_BLOCK", blockData = mushroomBlockData(setOf(EAST, SOUTH, UP)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::TITANIUM_BLOCK) ) - )) + ) { CustomItems.TITANIUM_BLOCK }) - val RAW_TITANIUM_BLOCK = register(CustomBlock( + val RAW_TITANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "RAW_TITANIUM_BLOCK", blockData = mushroomBlockData(setOf(EAST)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_TITANIUM_BLOCK) ) - )) + ) { CustomItems.RAW_TITANIUM_BLOCK }) - val URANIUM_ORE = register(CustomBlock( + val URANIUM_ORE : CustomBlock = register(CustomBlock( identifier = "URANIUM_ORE", blockData = mushroomBlockData(setOf(UP)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_URANIUM) ) - )) + ) { CustomItems.URANIUM_ORE }) - val URANIUM_BLOCK = register(CustomBlock( + val URANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "URANIUM_BLOCK", blockData = mushroomBlockData(setOf(EAST, NORTH, SOUTH, WEST)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::URANIUM_BLOCK) ) - )) + ) { CustomItems.URANIUM_BLOCK }) - val ENRICHED_URANIUM_BLOCK = register(CustomBlock( + val ENRICHED_URANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "ENRICHED_URANIUM_BLOCK", blockData = mushroomBlockData(setOf(EAST, WEST)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ENRICHED_URANIUM_BLOCK) ) - )) + ) { CustomItems.ENRICHED_URANIUM_BLOCK }) - val NETHERITE_CASING = register(CustomBlock( + val NETHERITE_CASING : CustomBlock = register(CustomBlock( identifier = "NETHERITE_CASING", blockData = mushroomBlockData(setOf(WEST,NORTH,DOWN,UP)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::NETHERITE_CASING) ) - )) + ) { CustomItems.NETHERITE_CASING }) - val RAW_URANIUM_BLOCK = register(CustomBlock( + val RAW_URANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "RAW_URANIUM_BLOCK", blockData = mushroomBlockData(setOf(SOUTH)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_URANIUM_BLOCK) ) - )) + ) { CustomItems.RAW_ALUMINUM_BLOCK }) - val SUPERCONDUCTOR_BLOCK = register(CustomBlock( + val SUPERCONDUCTOR_BLOCK : CustomBlock = register(CustomBlock( identifier = "SUPERCONDUCTOR_BLOCK", blockData = mushroomBlockData(setOf(SOUTH, DOWN)), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::SUPERCONDUCTOR_BLOCK) ) - )) + ) { CustomItems.SUPERCONDUCTOR_BLOCK }) - val BATTLECRUISER_REACTOR_CORE = register(CustomBlock( + val BATTLECRUISER_REACTOR_CORE : CustomBlock = register(CustomBlock( identifier = "BATTLECRUISER_REACTOR_CORE", blockData = mushroomBlockData(setOf(NORTH, UP, WEST)), drops = BlockLoot( requiredTool = null, drops = customItemDrop(CustomItemRegistry::BATTLECRUISER_REACTOR_CORE) ) - )) + ) { CustomItems.BATTLECRUISER_REACTOR_CORE }) - val BARGE_REACTOR_CORE = register(CustomBlock( + val BARGE_REACTOR_CORE : CustomBlock = register(CustomBlock( identifier = "BARGE_REACTOR_CORE", blockData = mushroomBlockData(setOf(NORTH, EAST, WEST)), drops = BlockLoot( requiredTool = null, drops = customItemDrop(CustomItemRegistry::BARGE_REACTOR_CORE) ) - )) + ) { CustomItems.BARGE_REACTOR_CORE }) - val CRUISER_REACTOR_CORE = register(CustomBlock( + val CRUISER_REACTOR_CORE : CustomBlock = register(CustomBlock( identifier = "CRUISER_REACTOR_CORE", blockData = mushroomBlockData(setOf(NORTH, DOWN, WEST)), drops = BlockLoot( requiredTool = null, drops = customItemDrop(CustomItemRegistry::CRUISER_REACTOR_CORE) ) - )) + ) { CustomItems.CRUISER_REACTOR_CORE }) private fun customItemDrop(customItem: Supplier, amount: Int = 1): Supplier> { return customItem.map { item -> listOf(item.constructItemStack(amount)) } @@ -233,8 +234,11 @@ object CustomBlocks { open class CustomBlock( val identifier: String, val blockData: BlockData, - val drops: BlockLoot -) + val drops: BlockLoot, + private val customBlockItem: Supplier +) { + val customItem get() = customBlockItem.get() +} data class BlockLoot( val requiredTool: Supplier? = Supplier { Tool.PICKAXE }, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt index a4c36ac446..cf04e955dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt @@ -1,10 +1,17 @@ package net.horizonsend.ion.server.features.custom.blocks +import net.horizonsend.ion.server.features.custom.items.CustomBlockItem import org.bukkit.block.Block import org.bukkit.block.data.BlockData import org.bukkit.event.player.PlayerInteractEvent +import java.util.function.Supplier -abstract class InteractableCustomBlock(identifier: String, blockData: BlockData, drops: BlockLoot) : CustomBlock(identifier, blockData, drops) { +abstract class InteractableCustomBlock( + identifier: String, + blockData: BlockData, + drops: BlockLoot, + customBlockItem: Supplier +) : CustomBlock(identifier, blockData, drops, customBlockItem) { open fun onRightClick(event: PlayerInteractEvent, block: Block) {} open fun onLeftClick(event: PlayerInteractEvent, block: Block) {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 80c252cc91..2ed01c0059 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -45,7 +45,8 @@ object MultiblockWorkbench : InteractableCustomBlock( drops = BlockLoot( requiredTool = null, drops = customItemDrop(CustomItems::MULTIBLOCK_WORKBENCH, 1) - ) + ), + customBlockItem = { CustomItems.MULTIBLOCK_WORKBENCH } ) { private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index d3de7343c3..154034b1c2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component @@ -36,7 +37,9 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { it.displayName(ofChildren(Component.text("Packaged "), multiblock.getDisplayName()).itemName) it.lore(listOf( Component.text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", NamedTextColor.GRAY).itemName, - Component.text("Variant: ${multiblock.javaClass.simpleName}", NamedTextColor.GRAY).itemName + Component.text("Variant: ${multiblock.javaClass.simpleName}", NamedTextColor.GRAY).itemName, + Component.text("Left click to preview", NamedTextColor.GRAY).itemName, + Component.text("Right click to place", NamedTextColor.GRAY).itemName )) } } @@ -76,4 +79,22 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { itemStack.amount-- } + + override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + if (livingEntity !is Player) return + + val packagedData = PrePackaged.getTokenData(itemStack) ?: run { + livingEntity.userError("The packaged multiblock has no data!") + return + } + + val origin = PrePackaged.getOriginFromPlacement( + event.clickedBlock ?: return, + livingEntity.facing, + packagedData.shape + ) + + val locations = packagedData.shape.getLocations(livingEntity.facing).map { Vec3i(origin.x, origin.y, origin.z).plus(it) } + livingEntity.highlightBlocks(locations, 100L) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index 70b4d8edfd..b765a319a5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.custom.items.misc import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.multiblock.PrePackaged +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text @@ -10,12 +12,14 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType object Wrench : CustomItem("WRENCH") { override fun constructItemStack(): ItemStack { return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { it.setCustomModelData(8000) it.displayName(text("Wrench").itemName) + it.persistentDataContainer.set(CUSTOM_ITEM, PersistentDataType.STRING, identifier) } } @@ -33,6 +37,8 @@ object Wrench : CustomItem("WRENCH") { } private fun tryPickUpMultiblock(player: Player, sign: Sign) { + val item = PrePackaged.pickUpStructure(player, sign) ?: return + sign.world.dropItem(sign.location.toCenterLocation(), item) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt index efdadfba41..b39cab8d94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockAccess.kt @@ -31,6 +31,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority import org.bukkit.event.block.Action import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.player.PlayerInteractEvent @@ -278,8 +279,9 @@ object MultiblockAccess : IonServerComponent() { multiblockType.onSignInteract(sign, event.player, event) } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun onPlayerBreakBlock(event: BlockBreakEvent) { + if (event.isCancelled) return if (getBlockTypeSafe(event.block.world, event.block.x, event.block.y, event.block.z)?.isSign == false) return val sign = event.block.state as? Sign ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index bc59e7a12e..6ac67fbfa8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -2,13 +2,22 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.front +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe +import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.isSign +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text import org.bukkit.Material @@ -18,15 +27,19 @@ import org.bukkit.block.Chest import org.bukkit.block.Sign import org.bukkit.block.data.BlockData import org.bukkit.block.data.Directional +import org.bukkit.block.data.type.WallSign import org.bukkit.block.sign.Side import org.bukkit.entity.Player +import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.inventory.EquipmentSlot import org.bukkit.inventory.Inventory +import org.bukkit.inventory.InventoryHolder import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.BlockStateMeta import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import org.bukkit.persistence.PersistentDataType.STRING object PrePackaged { fun getOriginFromPlacement(clickedBlock: Block, direction: BlockFace, shape: MultiblockShape): Block { @@ -115,55 +128,85 @@ object PrePackaged { } if (multiblock is SignlessStarshipWeaponMultiblock<*>) return + val signItem: ItemStack? = itemSource?.contents?.firstOrNull { it?.type?.isSign == true } + + // If there is an item source but no sign then there is not one available + if (itemSource != null && signItem == null) return + + val signType = signItem?.type?.let { getWallSignType(it) } ?: Material.OAK_WALL_SIGN // Add sign val signPosition = origin.getRelative(direction.oppositeFace, 1) - val signData = Material.OAK_WALL_SIGN.createBlockData { signData -> + val signData = signType.createBlockData { signData -> signData as Directional signData.facing = direction.oppositeFace } signPosition.blockData = signData + val sign = signPosition.state as Sign - // Set the detection name just in case the setup fails - sign.getSide(Side.FRONT).line(0, text("[${multiblock.name}]")) - sign.update() + val signItemMeta = signItem?.itemMeta + if (signItemMeta is BlockStateMeta) { + val accurateState = signItemMeta.blockState as Sign + for ((line, component) in accurateState.front().lines().withIndex()) { + sign.front().line(line, component) + } + + accurateState.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData)?.let { + sign.persistentDataContainer.set(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData, it) + } + + accurateState.persistentDataContainer.get(MULTIBLOCK, STRING)?.let { + sign.persistentDataContainer.set(MULTIBLOCK, STRING, it) + } + + sign.update() + + MultiblockEntities.loadFromSign(sign) + } else { + // Set the detection name just in case the setup fails + sign.getSide(Side.FRONT).line(0, text("[${multiblock.name}]")) + sign.update() - MultiblockAccess.tryDetectMultiblock(player, sign, direction, false) + MultiblockAccess.tryDetectMultiblock(player, sign, direction, false) - multiblock.setupSign(player, sign) + multiblock.setupSign(player, sign) + } } fun getTokenData(itemStack: ItemStack): Multiblock? { - val data = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER) ?: return null - val storageName = data.get(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING)!! + val data = itemStack.itemMeta.persistentDataContainer.get(MULTIBLOCK, PersistentDataType.TAG_CONTAINER) ?: return null + val storageName = data.get(MULTIBLOCK, STRING)!! return MultiblockRegistration.getByStorageName(storageName)!! } fun setTokenData(multiblock: Multiblock, destination: PersistentDataContainer) { val pdc = destination.adapterContext.newPersistentDataContainer() - pdc.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.STRING, multiblock.javaClass.simpleName) + pdc.set(MULTIBLOCK, STRING, multiblock.javaClass.simpleName) - destination.set(NamespacedKeys.MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) + destination.set(MULTIBLOCK, PersistentDataType.TAG_CONTAINER, pdc) } /** Moves the needed materials for the provided multiblock from the list of items to the destination inventory */ - fun packageFrom(items: List, multiblock: Multiblock, destination: Inventory) { - val itemRequirements = multiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } + private fun packageFrom(items: List, multiblock: Multiblock, destination: Inventory) { + val itemRequirements = getRequirements(multiblock) val missing = mutableListOf() for (blockRequirement in itemRequirements) { val requirement = blockRequirement.itemRequirement - val success = items.firstOrNull { requirement.itemCheck(it) && requirement.consume(it) } + val success = items.firstOrNull { requirement.itemCheck(it) && requirement.consume(it.clone()) } if (success == null) { missing.add(blockRequirement) continue } - val amount = requirement.amountConsumed(success) - LegacyItemUtils.addToInventory(destination, success.asQuantity(amount)) + val toAdd = success.clone() + requirement.consume(success) + + val amount = requirement.amountConsumed(toAdd) + LegacyItemUtils.addToInventory(destination, toAdd.asQuantity(amount)) } } @@ -186,10 +229,10 @@ object PrePackaged { fun checkRequirements(available: Iterable, multiblock: Multiblock): List { val items = available.mapTo(mutableListOf()) { it.clone() } - val itemRequirements = multiblock.shape.getRequirementMap(BlockFace.NORTH).map { it.value } + val requirements = getRequirements(multiblock) val missing = mutableListOf() - for (blockRequirement in itemRequirements) { + for (blockRequirement in requirements) { val requirement = blockRequirement.itemRequirement if (items.any { requirement.itemCheck(it) && requirement.consume(it) }) continue missing.add(blockRequirement) @@ -197,4 +240,90 @@ object PrePackaged { return missing } + + fun pickUpStructure(player: Player, sign: Sign): ItemStack? { + val multiblockType = MultiblockAccess.getFast(sign) ?: return null + if (multiblockType is EntityMultiblock<*>) { + // Just in case + multiblockType.getMultiblockEntity(sign, true)?.saveToSign() + } + + val structureDirection = sign.getFacing().oppositeFace + val structureOrigin = MultiblockEntity.getOriginFromSign(sign) + + if (!multiblockType.shape.checkRequirements(structureOrigin, structureDirection, false)) return null + + val requirements = multiblockType.shape.getRequirementMap(structureDirection) + + val toBreak = mutableListOf() + val items = mutableListOf() + + val signItem = ItemStack(getNormalSignType(sign.type)).updateMeta { meta -> + meta as BlockStateMeta + meta.blockState = sign + } + + for ((offset, requirement) in requirements) { + val realBlock = structureOrigin.getRelativeIfLoaded(offset.x, offset.y, offset.z) ?: return null + if (!BlockBreakEvent(sign.block, player).callEvent()) return null + toBreak.add(realBlock) + + val item = requirement.itemRequirement.toItemStack(realBlock.blockData) + items.add(item) + } + + items.add(signItem) + toBreak.add(sign.block) + + if (!BlockBreakEvent(sign.block, player).callEvent()) return null + + toBreak.asReversed().forEach { + val state = it.state + if (state is InventoryHolder) { + for (item in state.inventory.filterNotNull()) { + state.world.dropItemNaturally(state.location.toCenterLocation(), item) + } + } + + it.setType(Material.AIR, false) + } + + return createPackagedItem(items, multiblockType) + } + + private fun getRequirements(multiblock: Multiblock): List = multiblock.shape.getRequirementMap(BlockFace.NORTH).values.plus(signRequirement) + + private val signRequirement = BlockRequirement( + "any sign", + Material.OAK_WALL_SIGN.createBlockData(), + syncCheck@{ block, face, loadChunks -> + val data = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) ?: return@syncCheck false + if (data !is WallSign) return@syncCheck false + if (data.facing != face.oppositeFace) return@syncCheck false + true + }, + BlockRequirement.ItemRequirement( + itemCheck = { it.type.isSign }, + amountConsumed = { 1 }, + toBlock = { item -> + val wallVariant = getWallSignType(item.type) + wallVariant.createBlockData() + }, + toItemStack = { ItemStack(getNormalSignType(it.material)) } + ) + ).addPlacementModification { blockFace, blockData -> + blockData as WallSign + blockData.facing = blockFace.oppositeFace + } + + private fun getWallSignType(material: Material): Material { + val variant = material.name.removeSuffix("_SIGN") + return runCatching { Material.valueOf(variant + "_WALL_SIGN") }.getOrDefault(Material.OAK_WALL_SIGN) + } + + private fun getNormalSignType(material: Material): Material { + if (material.isSign && !material.isWallSign) return material + val variant = material.name.removeSuffix("_WALL_SIGN") + return runCatching { Material.valueOf(variant + "_SIGN") }.getOrDefault(Material.OAK_SIGN) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 2405b577e8..4c93242450 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -10,15 +10,12 @@ class BlockRequirement( val alias: String, var example: BlockData, private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, - private val dataCheck: (BlockData) -> Boolean, val itemRequirement: ItemRequirement ) { private val placementModifications: MutableList<(BlockFace, BlockData) -> Unit> = mutableListOf() operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) - fun checkBlockData(data: BlockData) = dataCheck.invoke(data) - fun setExample(blockData: BlockData): BlockRequirement { this.example = blockData @@ -50,7 +47,8 @@ class BlockRequirement( class ItemRequirement( val itemCheck: (ItemStack) -> Boolean, val amountConsumed: (ItemStack) -> Int, - val toBlock: (ItemStack) -> BlockData + val toBlock: (ItemStack) -> BlockData, + val toItemStack: (BlockData) -> ItemStack ) { fun consume(itemStack: ItemStack): Boolean { itemStack.amount -= amountConsumed(itemStack) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 5f1d058149..1e5a67071e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -50,6 +50,7 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.Furnace import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Slab.Type.DOUBLE +import org.bukkit.inventory.ItemStack import java.util.EnumSet class MultiblockShape { @@ -232,11 +233,11 @@ class MultiblockShape { alias = type.toString(), example = type.createBlockData(), syncCheck = { block, _, loadChunks -> if (loadChunks) block.type == type else block.getTypeSafe() == type }, - dataCheck = { type == it.material }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { type == it.type }, amountConsumed = { 1 }, - toBlock = { item -> item.type.createBlockData() } + toBlock = { item -> item.type.createBlockData() }, + toItemStack = { block -> ItemStack(block.material) } ) ) @@ -252,11 +253,11 @@ class MultiblockShape { syncCheck = { block, _, loadChunks -> typeSet.contains(if (loadChunks) block.type else block.getTypeSafe() ?: return@BlockRequirement false) }, - dataCheck = { typeSet.contains(it.material) }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { typeSet.contains(it.type) }, amountConsumed = { 1 }, - toBlock = { item -> item.type.createBlockData() } + toBlock = { item -> item.type.createBlockData() }, + toItemStack = { block -> ItemStack(block.material) } ) ) @@ -274,11 +275,11 @@ class MultiblockShape { getBlockDataSafe(block.world, block.x, block.y, block.z)?.let { CustomBlocks.getByBlockData(it) } } === customBlock }, - dataCheck = { CustomBlocks.getByBlockData(it) == customBlock }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { val customItem = it.customItem; customItem is CustomBlockItem && customItem.getCustomBlock() == customBlock }, amountConsumed = { 1 }, - toBlock = { _ -> customBlock.blockData } + toBlock = { _ -> customBlock.blockData }, + toItemStack = { block -> CustomBlocks.getByBlockData(block)?.customItem?.constructItemStack() ?: ItemStack(Material.AIR) } ) ) @@ -331,11 +332,11 @@ class MultiblockShape { val blockData: BlockData? = if (loadChunks) block.blockData else getBlockDataSafe(block.world, block.x, block.y, block.z) blockData is Slab && blockData.type == DOUBLE }, - dataCheck = { it is Slab && it.type == DOUBLE }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) }, amountConsumed = { 2 }, - toBlock = { item -> (item.type.createBlockData() as Slab).apply { this.type = DOUBLE } } + toBlock = { item -> (item.type.createBlockData() as Slab).apply { this.type = DOUBLE } }, + toItemStack = { ItemStack(it.material, 2) } ), ) ) @@ -352,7 +353,6 @@ class MultiblockShape { (blockData is Slab && blockData.type == DOUBLE) || TERRACOTTA_TYPES.contains(blockType) }, - dataCheck = { (it is Slab && it.type == DOUBLE) || it.material.isTerracotta }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { (it.type.isSlab && it.amount >= 2) || it.type.isTerracotta }, amountConsumed = { if (it.type.isSlab) 2 else 1 }, @@ -361,6 +361,10 @@ class MultiblockShape { if (type.isSlab) { (type.createBlockData() as Slab).apply { this.type = DOUBLE } } else type.createBlockData() + }, + { block -> + val type = block.material + if (type.isSlab) ItemStack(type, 2) else ItemStack(type) } ), ) @@ -491,11 +495,11 @@ class MultiblockShape { val facing = blockData.getValue(AbstractFurnaceBlock.FACING).blockFace return@check facing == inward.oppositeFace }, - dataCheck = { it is Furnace }, itemRequirement = BlockRequirement.ItemRequirement( itemCheck = { it.type == Material.FURNACE }, amountConsumed = { 1 }, - toBlock = { Material.FURNACE.createBlockData() } + toBlock = { Material.FURNACE.createBlockData() }, + toItemStack = { ItemStack(Material.FURNACE) } ) ).addPlacementModification { direction, data -> data as Furnace From 2b78b201edcbc871c776532896ef7f1aecc08487 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 20:15:33 -0600 Subject: [PATCH 326/500] only setup multiblock entity if it had the data, optionally allow block sharing --- .../custom/items/misc/MultiblockToken.kt | 4 +- .../custom/items/misc/PackagedMultiblock.kt | 14 +++- .../server/features/multiblock/PrePackaged.kt | 66 ++++++++++++------- 3 files changed, 54 insertions(+), 30 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index 92172c831b..00d2466174 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -63,10 +63,10 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { packagedData.shape ) - val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.shape) + val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.shape, livingEntity.isSneaking) if (obstructions.isNotEmpty()) { - livingEntity.userError("Placement is obstructed!") + livingEntity.userError("Placement is obstructed! Crouch to enable block sharing.") livingEntity.highlightBlocks(obstructions, 50L) return } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index 154034b1c2..e2df67584b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -58,16 +58,17 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { if (event == null) return + val direction = livingEntity.facing val origin = PrePackaged.getOriginFromPlacement( event.clickedBlock ?: return, - livingEntity.facing, + direction, packagedData.shape ) - val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.shape) + val obstructions = PrePackaged.checkObstructions(origin, livingEntity.facing, packagedData.shape, livingEntity.isSneaking) if (obstructions.isNotEmpty()) { - livingEntity.userError("Placement is obstructed!") + livingEntity.userError("Placement is obstructed! Crouch to enable block sharing.") livingEntity.highlightBlocks(obstructions, 50L) return } @@ -75,6 +76,13 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, inventory) }.onFailure { livingEntity.information("ERROR: $it") it.printStackTrace() + }.onSuccess { + // Drop remaining items in packaged multi + val dropLocation = origin.getRelative(direction.oppositeFace).location.toCenterLocation() + + for (item in inventory.contents.filterNotNull()) { + livingEntity.world.dropItem(dropLocation, item) + } } itemStack.amount-- diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 6ac67fbfa8..71b93c4a31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -51,20 +51,26 @@ object PrePackaged { .getRelative(BlockFace.DOWN, minY) // Go up (down negative blocks) until the origin is high enough to fit the blocks below it } - fun checkObstructions(origin: Block, direction: BlockFace, shape: MultiblockShape): List { + /** + * @param allowCorrect Allows for correctly placed blocks that are already in the world to be ignored as obstructions + **/ + fun checkObstructions(origin: Block, direction: BlockFace, shape: MultiblockShape, allowCorrect: Boolean): List { val requirements = shape.getRequirementMap(direction) val obstructed = mutableListOf() - for ((offset, _) in requirements) { + for ((offset, requirement) in requirements) { val offsetBlock = origin.getRelativeIfLoaded(offset.x, offset.y, offset.z) + val vec = Vec3i(origin.x, origin.y, origin.z).plus(offset) if (offsetBlock == null) { - obstructed.add(Vec3i(origin.x, origin.y, origin.z).plus(offset)) + obstructed.add(vec) continue } - if (!offsetBlock.type.isAir) { - obstructed.add(Vec3i(origin.x, origin.y, origin.z).plus(offset)) + if (allowCorrect) { + if (!requirement.invoke(offsetBlock, direction, false) && !offsetBlock.type.isAir) obstructed.add(vec) + } else if (!offsetBlock.type.isAir) { + obstructed.add(vec) } } @@ -84,6 +90,11 @@ object PrePackaged { val absolute = Vec3i(origin.x, origin.y, origin.z) + offset val (x, y, z) = absolute + val existingBlock = origin.world.getBlockAt(x, y, z) + + // Already placed, assuming allow merges + if (requirement.invoke(existingBlock, direction, false)) continue + var usedItem: ItemStack? = null if (itemSource != null) { @@ -96,8 +107,6 @@ object PrePackaged { } } - val existingBlock = origin.world.getBlockAt(x, y, z) - val event = BlockPlaceEvent( existingBlock, existingBlock.state, @@ -147,32 +156,39 @@ object PrePackaged { val sign = signPosition.state as Sign val signItemMeta = signItem?.itemMeta - if (signItemMeta is BlockStateMeta) { + if (signItemMeta is BlockStateMeta && signItemMeta.hasBlockState()) { val accurateState = signItemMeta.blockState as Sign - for ((line, component) in accurateState.front().lines().withIndex()) { - sign.front().line(line, component) - } - accurateState.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData)?.let { - sign.persistentDataContainer.set(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData, it) - } + if (accurateState.persistentDataContainer.has(MULTIBLOCK)) { + for ((line, component) in accurateState.front().lines().withIndex()) { + sign.front().line(line, component) + } - accurateState.persistentDataContainer.get(MULTIBLOCK, STRING)?.let { - sign.persistentDataContainer.set(MULTIBLOCK, STRING, it) + accurateState.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData)?.let { + sign.persistentDataContainer.set(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData, it) + } + + accurateState.persistentDataContainer.get(MULTIBLOCK, STRING)?.let { + sign.persistentDataContainer.set(MULTIBLOCK, STRING, it) + } + + sign.update() + + MultiblockEntities.loadFromSign(sign) + signItem.amount-- + return } + } - sign.update() + signItem?.let { it.amount-- } - MultiblockEntities.loadFromSign(sign) - } else { - // Set the detection name just in case the setup fails - sign.getSide(Side.FRONT).line(0, text("[${multiblock.name}]")) - sign.update() + // Set the detection name just in case the setup fails + sign.getSide(Side.FRONT).line(0, text("[${multiblock.name}]")) + sign.update() - MultiblockAccess.tryDetectMultiblock(player, sign, direction, false) + MultiblockAccess.tryDetectMultiblock(player, sign, direction, false) - multiblock.setupSign(player, sign) - } + multiblock.setupSign(player, sign) } fun getTokenData(itemStack: ItemStack): Multiblock? { From af4681a9f051ff84e1def5b2b0268ba7afbaf198 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 20:40:06 -0600 Subject: [PATCH 327/500] add slab preset --- .../server/features/multiblock/util/PrepackagedPreset.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt index 322b310787..2ef1084ee6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt @@ -7,6 +7,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.Bisected import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.Fence +import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Stairs object PrepackagedPreset { @@ -27,4 +28,12 @@ object PrepackagedPreset { face.forEach { pane.setFace(it[multiblockDirection], true) } } } + + fun slab(type: Slab.Type): BlockRequirement.() -> Unit = { + example = Material.STONE_BRICK_SLAB.createBlockData() + addPlacementModification { multiblockDirection: BlockFace, slab: BlockData -> + slab as Slab + slab.type = type + } + } } From 269a701b7ce0856090bc818b3c20bc36080f4962 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 20:51:24 -0600 Subject: [PATCH 328/500] more prepackaged presets --- .../multiblock/shape/BlockRequirement.kt | 1 + .../type/fluid/ElectrolysisMultiblock.kt | 46 +++++++++---------- .../type/fluid/storage/FluidTankMedium.kt | 20 ++++---- .../type/power/charger/ChargerMultiblock.kt | 18 ++++---- .../NavigationComputerMultiblockAdvanced.kt | 18 ++++---- .../multiblock/util/PrepackagedPreset.kt | 8 +++- .../utils/coordinates/RelativeFace.kt | 4 +- 7 files changed, 61 insertions(+), 54 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt index 4c93242450..e7c3738a2e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/BlockRequirement.kt @@ -12,6 +12,7 @@ class BlockRequirement( private val syncCheck: (Block, BlockFace, Boolean) -> Boolean, val itemRequirement: ItemRequirement ) { + var blockUpdate: Boolean = false //TODO impl private val placementModifications: MutableList<(BlockFace, BlockData) -> Unit> = mutableListOf() operator fun invoke(block: Block, inward: BlockFace, loadChunks: Boolean) = syncCheck.invoke(block, inward, loadChunks) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 9b83ea97e1..a2aba3574c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -33,10 +33,10 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_1 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_2 import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TANK_3 +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.BACKWARD +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.FORWARD import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.LEFT -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.OPPOSITE import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.RIGHT -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.SELF import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component @@ -69,39 +69,39 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock Unit = { example = Material.GLASS_PANE.createBlockData() addPlacementModification { multiblockDirection: BlockFace, pane: BlockData -> - pane as Fence + pane as MultipleFacing face.forEach { pane.setFace(it[multiblockDirection], true) } } } @@ -36,4 +36,8 @@ object PrepackagedPreset { slab.type = type } } + + fun blockUpdate(): BlockRequirement.() -> Unit = { + blockUpdate = true + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt index 3e9b429462..3d7c940bd6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt @@ -5,12 +5,12 @@ import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.block.BlockFace enum class RelativeFace { - SELF { + FORWARD { override fun get(face: BlockFace): BlockFace { return face } }, - OPPOSITE { + BACKWARD { override fun get(face: BlockFace): BlockFace { return face.oppositeFace } From a0a172ffb61cd7b7f98de5e7ea67f25602688341 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 21:21:16 -0600 Subject: [PATCH 329/500] Check for invalid multiblock entities on startup --- .../multiblock/manager/ChunkMultiblockManager.kt | 2 +- .../multiblock/manager/MultiblockManager.kt | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index a60bdfe44f..57ecd91996 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -96,7 +96,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag val entity = MultiblockEntities.loadFromData(multiblock, this, stored) // No need to save a load - addMultiblockEntity(entity, save = false) + addMultiblockEntity(entity, save = false, ensureSign = true) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 4a998540e9..e2e69f9a9e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -48,7 +49,16 @@ abstract class MultiblockManager(val log: Logger) { /** * Handles the addition of a multiblock entity **/ - fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true) { + fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true, ensureSign: Boolean = false) { + if (ensureSign) { + val signOrigin = MultiblockEntity.getSignFromOrigin(entity.world, entity.vec3i, entity.structureDirection) + if (!signOrigin.type.isWallSign) { + log.info("Removing invalid multiblock entity at ${entity.vec3i} on ${entity.world.name}") + entity.remove() + return + } + } + multiblockEntities[entity.locationKey] = entity entity.processLoad() @@ -67,7 +77,7 @@ abstract class MultiblockManager(val log: Logger) { /** * Upon the removal of a multiblock sign **/ - fun removeMultiblockEntity(x: Int, y: Int, z: Int): MultiblockEntity? { + fun removeMultiblockEntity(x: Int, y: Int, z: Int, save: Boolean = true): MultiblockEntity? { val key = toBlockKey(x, y, z) val entity = multiblockEntities.remove(key) @@ -77,6 +87,8 @@ abstract class MultiblockManager(val log: Logger) { entity?.processRemoval() + if (save) save() + return entity } From a7c9cfc033964ec1065b799cafb0341ef591b996 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 24 Nov 2024 22:58:43 -0600 Subject: [PATCH 330/500] Prevent power / fluid dupe --- .../custom/items/misc/MultiblockToken.kt | 2 +- .../custom/items/misc/PackagedMultiblock.kt | 6 ++- .../features/custom/items/misc/Wrench.kt | 4 +- .../server/features/multiblock/PrePackaged.kt | 50 ++++++++++++------- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index 00d2466174..190977b9ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -71,7 +71,7 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { return } - runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, null) } + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, null, null) } itemStack.amount-- } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index e2df67584b..c1e851ad0a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -7,7 +7,9 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.text.itemName @@ -73,7 +75,9 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { return } - runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, inventory) }.onFailure { + val entityData = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) + + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, inventory, entityData) }.onFailure { livingEntity.information("ERROR: $it") it.printStackTrace() }.onSuccess { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index b765a319a5..f42a92ad94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -37,9 +37,7 @@ object Wrench : CustomItem("WRENCH") { } private fun tryPickUpMultiblock(player: Player, sign: Sign) { - val item = PrePackaged.pickUpStructure(player, sign) ?: return - sign.world.dropItem(sign.location.toCenterLocation(), item) - + PrePackaged.pickUpStructure(player, sign) } private fun tryEditFilter(player: Player, sign: Sign) { // State TBD diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index 71b93c4a31..c12d59b18d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -2,8 +2,11 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.loadFromData +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.setMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.shape.BlockRequirement import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock @@ -82,7 +85,7 @@ object PrePackaged { return obstructed } - fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock, itemSource: Inventory?) { + fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock, itemSource: Inventory?, entityData: PersistentMultiblockData?) { val requirements = multiblock.shape.getRequirementMap(direction) val placements = mutableMapOf() @@ -155,7 +158,22 @@ object PrePackaged { val sign = signPosition.state as Sign + if (entityData != null && multiblock is EntityMultiblock<*>) { + entityData.x = origin.x + entityData.y = origin.y + entityData.z = origin.z + entityData.signOffset = sign.getFacing().oppositeFace + + setMultiblockEntity(sign.world, origin.x, origin.y, origin.z) { manager -> + val new = loadFromData(multiblock, manager, entityData) + if (new is LegacyMultiblockEntity) new.loadFromSign(sign) + + new + } + } + val signItemMeta = signItem?.itemMeta + if (signItemMeta is BlockStateMeta && signItemMeta.hasBlockState()) { val accurateState = signItemMeta.blockState as Sign @@ -164,17 +182,12 @@ object PrePackaged { sign.front().line(line, component) } - accurateState.persistentDataContainer.get(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData)?.let { - sign.persistentDataContainer.set(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData, it) - } - accurateState.persistentDataContainer.get(MULTIBLOCK, STRING)?.let { sign.persistentDataContainer.set(MULTIBLOCK, STRING, it) } sign.update() - MultiblockEntities.loadFromSign(sign) signItem.amount-- return } @@ -257,17 +270,14 @@ object PrePackaged { return missing } - fun pickUpStructure(player: Player, sign: Sign): ItemStack? { - val multiblockType = MultiblockAccess.getFast(sign) ?: return null - if (multiblockType is EntityMultiblock<*>) { - // Just in case - multiblockType.getMultiblockEntity(sign, true)?.saveToSign() - } + fun pickUpStructure(player: Player, sign: Sign) { + val multiblockType = MultiblockAccess.getFast(sign) ?: return + val entityData = (multiblockType as? EntityMultiblock<*>)?.getMultiblockEntity(sign)?.store() val structureDirection = sign.getFacing().oppositeFace val structureOrigin = MultiblockEntity.getOriginFromSign(sign) - if (!multiblockType.shape.checkRequirements(structureOrigin, structureDirection, false)) return null + if (!multiblockType.shape.checkRequirements(structureOrigin, structureDirection, false)) return val requirements = multiblockType.shape.getRequirementMap(structureDirection) @@ -280,8 +290,8 @@ object PrePackaged { } for ((offset, requirement) in requirements) { - val realBlock = structureOrigin.getRelativeIfLoaded(offset.x, offset.y, offset.z) ?: return null - if (!BlockBreakEvent(sign.block, player).callEvent()) return null + val realBlock = structureOrigin.getRelativeIfLoaded(offset.x, offset.y, offset.z) ?: return + if (!BlockBreakEvent(sign.block, player).callEvent()) return toBreak.add(realBlock) val item = requirement.itemRequirement.toItemStack(realBlock.blockData) @@ -291,7 +301,7 @@ object PrePackaged { items.add(signItem) toBreak.add(sign.block) - if (!BlockBreakEvent(sign.block, player).callEvent()) return null + if (!BlockBreakEvent(sign.block, player).callEvent()) return toBreak.asReversed().forEach { val state = it.state @@ -304,7 +314,13 @@ object PrePackaged { it.setType(Material.AIR, false) } - return createPackagedItem(items, multiblockType) + val item = createPackagedItem(items, multiblockType) + + if (entityData != null) { + item.updateMeta { it.persistentDataContainer.set(MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData, entityData) } + } + + sign.world.dropItem(sign.location.toCenterLocation(), item) } private fun getRequirements(multiblock: Multiblock): List = multiblock.shape.getRequirementMap(BlockFace.NORTH).values.plus(signRequirement) From 7803496c5a64e590f6070705d41e14703cbdbc51 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 25 Nov 2024 00:31:50 -0600 Subject: [PATCH 331/500] Get relative face from 2 faces --- .../miscellaneous/utils/coordinates/RelativeFace.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt index 3d7c940bd6..de1e5e034c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt @@ -27,4 +27,16 @@ enum class RelativeFace { }; abstract operator fun get(face: BlockFace): BlockFace + + companion object { + operator fun get(forward: BlockFace, relative: BlockFace): RelativeFace { + return when { + forward == relative -> FORWARD + forward.oppositeFace == relative -> BACKWARD + forward.rightFace == relative -> RIGHT + forward.leftFace == relative -> LEFT + else -> throw IllegalArgumentException("Unsupported relationship! Forward: $forward, relative: $relative.") + } + } + } } From 30def722e5aed7f981a3116f5a5ec7144741da3b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 25 Nov 2024 01:27:53 -0600 Subject: [PATCH 332/500] StructureCreator command --- .../server/command/admin/StructureCreator.kt | 124 ++++++++++++++++++ .../miscellaneous/registrations/Commands.kt | 2 + 2 files changed, 126 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt new file mode 100644 index 0000000000..c1dd2eb0bf --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -0,0 +1,124 @@ +package net.horizonsend.ion.server.command.admin + +import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.Default +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.command.SLCommand +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.isConcrete +import net.horizonsend.ion.server.miscellaneous.utils.isGlassPane +import net.horizonsend.ion.server.miscellaneous.utils.isSlab +import net.horizonsend.ion.server.miscellaneous.utils.isStairs +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.event.ClickEvent +import org.bukkit.Material +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.block.data.type.GlassPane +import org.bukkit.block.data.type.Slab +import org.bukkit.block.data.type.Stairs +import org.bukkit.entity.Player + +@CommandAlias("structurecreator") +object StructureCreator : SLCommand() { + @Default + fun onCreate(sender: Player) { + sender.information("Will attempt to create a multiblock structure using the block in your crosshair as an origin, and the way you are facing as forwards.") + + val forwards = sender.facing + val right = forwards.rightFace + + val selection = requireSelection(sender) + val origin = sender.getTargetBlockExact(10) ?: fail { "You're not targeting a block!" } + + val selectionMin = selection.minimumPoint + val selectionMax = selection.maximumPoint + + val requirements = mutableMapOf() + + for (x in selectionMin.x..selectionMax.x) { + for (y in selectionMin.y..selectionMax.y) { + for (z in selectionMin.z..selectionMax.z) { + val relativeX = x - origin.x + val relativeY = y - origin.y + val relativeZ = z - origin.z + + val rightOffset = (right.modX * relativeX) + (right.modZ * relativeZ) + val forwardOffset = (forwards.modX * relativeX) + (forwards.modZ * relativeZ) + + val data = sender.world.getBlockData(x, y, z) + if (data.material.isAir) continue + requirements[Vec3i(rightOffset, relativeY, forwardOffset)] = getBlockRequirement(data, forwards) + } + } + } + + var structure = "override fun MultiblockShape.buildStructure() {" + + for ((z, zEntries) in requirements.entries.groupBy { it.key.z }) { + val yGrouped = zEntries.groupBy { it.key.y } + structure += "\n\tz($z) {" + + for ((y, yEntries) in yGrouped) { + val xGrouped = yEntries.groupBy { it.key.x } + structure += "\n\t\ty($y) {" + + for ((x, xEntries) in xGrouped) { + if (xEntries.isEmpty()) continue + if (xEntries.size > 1) throw IllegalArgumentException("More than 1 placement in multiblock shape at $x, $y, $z") + + val xEntry = xEntries.first() + + structure += "\n\t\t\tx($x)${xEntry.value}" + } + + structure += "\n\t\t}" + } + + structure += "\n\t}" + } + + structure += "\n}" + + sender.sendMessage(Component.text(structure).hoverEvent(Component.text(structure)).clickEvent(ClickEvent.copyToClipboard(structure))) + } + + private fun getBlockRequirement(data: BlockData, forwards: BlockFace): String { + val customBlock = CustomBlocks.getByBlockData(data) + if (customBlock != null) return ".customBlock(CustomBlocks.${customBlock.identifier})" + + return when { + data.material.isConcrete -> ".carbyne()" + data.material == Material.FURNACE -> ".machineFurnace()" + + data.material.isStairs -> { + data as Stairs + val facing = RelativeFace[forwards, data.facing] + val half = data.half + val shape = data.shape + + ".anyStairs(PrepackagedPreset.stairs($facing, $half, shape = $shape))" + } + + data.material.isSlab -> { + data as Slab + val type = data.type + + if (type == Slab.Type.DOUBLE) return "PrepackagedPreset.doubleSlab()" + + ".anySlab(PrepackagedPreset.slab($type))" + } + + data.material.isGlassPane -> { + data as GlassPane + val faces = data.faces.map { RelativeFace[forwards, it] } + ".anyGlassPane(PrepackagedPreset.pane(${faces.joinToString { it.name }}))" + } + + else -> ".type(Material.${data.material.name})" + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt index 227105aa1b..29436416f6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.command.admin.IonChunkCommand import net.horizonsend.ion.server.command.admin.IonCommand import net.horizonsend.ion.server.command.admin.ItemDebugCommand import net.horizonsend.ion.server.command.admin.RemoveGhostShipCommand +import net.horizonsend.ion.server.command.admin.StructureCreator import net.horizonsend.ion.server.command.admin.WorldCommand import net.horizonsend.ion.server.command.economy.BazaarCommand import net.horizonsend.ion.server.command.economy.CityNpcCommand @@ -195,6 +196,7 @@ val commands: List = listOf( EnableProtectionMessagesCommand, IonSitCommand, SuicideCommand, + StructureCreator, NavigationCommand, DisplayDebug ) From 7cddbb63c3e24dbd3ab102844e689b3f934394b2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 25 Nov 2024 01:33:41 -0600 Subject: [PATCH 333/500] add permission --- .../horizonsend/ion/server/command/admin/StructureCreator.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index c1dd2eb0bf..6fafa1fd9f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.command.admin import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Default import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.SLCommand @@ -22,6 +23,7 @@ import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Stairs import org.bukkit.entity.Player +@CommandPermission("ion.admin.structurecreator") @CommandAlias("structurecreator") object StructureCreator : SLCommand() { @Default From 049c498b8f52e1135856f985f5a91a4adad0e3ff Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 25 Nov 2024 01:34:47 -0600 Subject: [PATCH 334/500] fix double slabs --- .../horizonsend/ion/server/command/admin/StructureCreator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index 6fafa1fd9f..287f5f2fd5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -109,7 +109,7 @@ object StructureCreator : SLCommand() { data as Slab val type = data.type - if (type == Slab.Type.DOUBLE) return "PrepackagedPreset.doubleSlab()" + if (type == Slab.Type.DOUBLE) return ".doubleSlab()" ".anySlab(PrepackagedPreset.slab($type))" } From 364445f87f19039816a0ea72cc29af4ff5a86011 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 25 Nov 2024 01:45:38 -0600 Subject: [PATCH 335/500] add more aliases --- .../server/command/admin/StructureCreator.kt | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index 287f5f2fd5..8c78ecb78f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -6,12 +6,17 @@ import co.aikar.commands.annotation.Default import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.isConcrete +import net.horizonsend.ion.server.miscellaneous.utils.isGlass import net.horizonsend.ion.server.miscellaneous.utils.isGlassPane import net.horizonsend.ion.server.miscellaneous.utils.isSlab import net.horizonsend.ion.server.miscellaneous.utils.isStairs +import net.horizonsend.ion.server.miscellaneous.utils.isTerracotta +import net.horizonsend.ion.server.miscellaneous.utils.isTrapdoor import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.kyori.adventure.text.event.ClickEvent @@ -90,10 +95,16 @@ object StructureCreator : SLCommand() { private fun getBlockRequirement(data: BlockData, forwards: BlockFace): String { val customBlock = CustomBlocks.getByBlockData(data) - if (customBlock != null) return ".customBlock(CustomBlocks.${customBlock.identifier})" + if (customBlock != null) return when (customBlock) { + CustomBlocks.TITANIUM_BLOCK -> ".titaniumBlock()" + CustomBlocks.ALUMINUM_BLOCK -> ".aluminumBlock()" + CustomBlocks.CHETHERITE_BLOCK -> ".chetheriteBlock()" + CustomBlocks.STEEL_BLOCK -> ".steelBlock()" + else -> ".customBlock(CustomBlocks.${customBlock.identifier})" + } return when { - data.material.isConcrete -> ".carbyne()" + data.material.isConcrete -> ".concrete()" data.material == Material.FURNACE -> ".machineFurnace()" data.material.isStairs -> { @@ -114,6 +125,41 @@ object StructureCreator : SLCommand() { ".anySlab(PrepackagedPreset.slab($type))" } + data.material.isTerracotta -> ".terracotta()" + data.material.isGlass -> ".anyGlass()" + data.material == Material.SEA_LANTERN -> ".seaLantern()" + data.material == Material.STONE_BRICKS -> ".stoneBrick()" + + data.material == Material.IRON_BLOCK -> ".ironBlock()" + data.material == Material.GOLD_BLOCK -> ".goldBlock()" + data.material == Material.DIAMOND_BLOCK -> ".diamondBlock()" + data.material == Material.NETHERITE_BLOCK -> ".netheriteBlock()" + data.material == Material.EMERALD_BLOCK -> ".emeraldBlock()" + data.material == Material.REDSTONE_BLOCK -> ".redstoneBlock()" + data.material == Material.LAPIS_BLOCK -> ".lapisBlock()" + + data.material == Wires.INPUT_COMPUTER_BLOCK -> ".wireInputComputer()" + data.material == Material.FLETCHING_TABLE -> ".fluidInput()" + data.material == Material.END_ROD -> ".endRod()" + data.material == EXTRACTOR_TYPE -> ".extractor()" + data.material == Material.HOPPER -> ".hopper()" + data.material == Material.DISPENSER -> ".dispenser()" + + data.material.isTrapdoor -> ".anyTrapdoor()" + + data.material == Material.SPONGE -> ".sponge()" + data.material == Material.WET_SPONGE -> ".sponge()" + + data.material == Material.OCHRE_FROGLIGHT -> ".thrusterBlock()" + data.material == Material.VERDANT_FROGLIGHT -> ".thrusterBlock()" + data.material == Material.PEARLESCENT_FROGLIGHT -> ".thrusterBlock()" + data.material == Material.GLOWSTONE -> ".thrusterBlock()" + data.material == Material.REDSTONE_LAMP -> ".thrusterBlock()" + data.material == Material.MAGMA_BLOCK -> ".thrusterBlock()" + data.material == Material.SEA_LANTERN -> ".thrusterBlock()" + + data.material == Material.LIGHTNING_ROD -> ".lightningRod()" + data.material.isGlassPane -> { data as GlassPane val faces = data.faces.map { RelativeFace[forwards, it] } From a75f8c4579462e6dfa80779b9cbcd5c64d368126 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 25 Nov 2024 12:11:58 -0600 Subject: [PATCH 336/500] Multiblock shape cleanup and standardization --- .../server/command/admin/StructureCreator.kt | 32 +-- .../multiblock/shape/MultiblockShape.kt | 128 +++++++----- .../type/ammo/AmmoLoaderMultiblock.kt | 6 +- .../type/ammo/AmmoPressMultiblock.kt | 6 +- .../type/ammo/MissileLoaderMultiblock.kt | 18 +- .../type/autocrafter/AutoCrafterMultiblock.kt | 8 +- .../defense/active/AntiAirCannonMultiblock.kt | 158 +++++++------- .../passive/areashield/AreaShield10.kt | 2 +- .../passive/areashield/AreaShield20.kt | 2 +- .../passive/areashield/AreaShield30.kt | 2 +- .../defense/passive/areashield/AreaShield5.kt | 2 +- .../ConnectedDockingTubeMultiblock.kt | 2 +- .../multiblock/type/drills/DrillMultiblock.kt | 4 +- .../farming/harvester/HarvesterMultiblock.kt | 2 +- .../type/farming/planter/PlanterMultiblock.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 30 +-- .../type/fluid/GasPowerPlantMultiblock.kt | 2 +- .../collector/PipedGasCollectorMultiblock.kt | 10 +- .../type/fluid/storage/FluidTankMedium.kt | 18 +- .../type/fluid/storage/FluidTankSmall.kt | 4 +- .../type/industry/CentrifugeMultiblock.kt | 2 +- .../type/industry/CircuitfabMultiblock.kt | 7 +- .../type/industry/CompressorMultiblock.kt | 4 +- .../type/industry/FabricatorMultiblock.kt | 7 +- .../type/industry/GasFurnaceMultiblock.kt | 4 +- .../type/industry/PlatePressMultiblock.kt | 7 +- .../type/misc/DisposalMultiblock.kt | 6 +- .../type/misc/ItemSplitterMultiblock.kt | 4 +- .../type/power/charger/ChargerMultiblock.kt | 2 +- .../power/generator/GeneratorMultiblock.kt | 2 +- .../powerfurnace/PowerFurnaceMultiblock.kt | 2 +- .../type/power/storage/PowerBankMultiblock.kt | 2 +- .../type/power/storage/PowerCellMultiblock.kt | 2 +- .../type/printer/CarbonProcessorMultiblock.kt | 2 +- .../type/printer/GlassPrinterMultiblock.kt | 2 +- .../type/printer/PrinterMultiblock.kt | 2 +- .../starship/checklist/AbstractReactorCore.kt | 193 ++++++++++++++++++ .../checklist/BargeReactorMultiBlock.kt | 193 +----------------- .../BattleCruiserReactorMultiblock.kt | 193 +----------------- .../checklist/CruiserReactorMultiblock.kt | 193 +----------------- .../AmplifiedGravityWellMultiblock.kt | 16 +- .../hyperdrive/HyperdriveMultiblockClass1.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass2.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass3.kt | 2 +- .../hyperdrive/HyperdriveMultiblockClass4.kt | 2 +- .../MiningLaserMultiblockTier1.kt | 60 +++--- .../MiningLaserMultiblockTier2.kt | 60 +++--- .../MiningLaserMultiblockTier3.kt | 108 +++++----- .../MiningLaserMultiblockTier4.kt | 108 +++++----- .../PulseCannonStarshipWeaponMultiblock.kt | 2 +- .../weapon/event/CthulhuBeamMultiblock.kt | 6 +- .../MiniPhaserStarshipWeaponMultiblock.kt | 2 +- .../AIHeavyLaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/AIPhaserStarshipWeaponMultiblock.kt | 2 +- .../ArsenalRocketStarshipWeaponMultiblock.kt | 2 +- .../heavy/DoomsdayDeviceWeaponMultiblock.kt | 8 +- .../HeavyLaserStarshipWeaponMultiblock.kt | 8 +- .../heavy/PhaserStarshipWeaponMultiblock.kt | 2 +- .../heavy/RocketStarshipWeaponMultiblock.kt | 12 +- .../weapon/turret/CycleTurretMultiblock.kt | 14 +- .../DisintegratorBeamWeaponMultiblock.kt | 8 +- .../weapon/turret/HeavyTurretMultiblock.kt | 10 +- .../weapon/turret/IonTurretMultiblock.kt | 24 +-- .../weapon/turret/QuadTurretMultiblock.kt | 50 ++--- .../weapon/turret/TriTurretMultiblock.kt | 14 +- .../multiblock/util/PrepackagedPreset.kt | 8 + 66 files changed, 736 insertions(+), 1065 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/AbstractReactorCore.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index 8c78ecb78f..955ba9388f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.isSlab import net.horizonsend.ion.server.miscellaneous.utils.isStairs import net.horizonsend.ion.server.miscellaneous.utils.isTerracotta import net.horizonsend.ion.server.miscellaneous.utils.isTrapdoor +import net.horizonsend.ion.server.miscellaneous.utils.isWall import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.kyori.adventure.text.event.ClickEvent @@ -100,11 +101,22 @@ object StructureCreator : SLCommand() { CustomBlocks.ALUMINUM_BLOCK -> ".aluminumBlock()" CustomBlocks.CHETHERITE_BLOCK -> ".chetheriteBlock()" CustomBlocks.STEEL_BLOCK -> ".steelBlock()" + CustomBlocks.ENRICHED_URANIUM_BLOCK -> ".enrichedUraniumBlock()" + CustomBlocks.NETHERITE_CASING -> ".netheriteCasing()" else -> ".customBlock(CustomBlocks.${customBlock.identifier})" } return when { - data.material.isConcrete -> ".concrete()" + data.material.isConcrete -> ".anyConcrete()" + data.material.isTerracotta -> ".anyTerracotta()" + data.material.isGlass -> ".anyGlass()" + data.material.isGlassPane -> { + data as GlassPane + val faces = data.faces.map { RelativeFace[forwards, it] } + ".anyGlassPane(PrepackagedPreset.pane(${faces.joinToString { it.name }}))" + } + data.material.isWall -> ".anyWall()" + data.material == Material.FURNACE -> ".machineFurnace()" data.material.isStairs -> { @@ -113,20 +125,18 @@ object StructureCreator : SLCommand() { val half = data.half val shape = data.shape - ".anyStairs(PrepackagedPreset.stairs($facing, $half, shape = $shape))" + ".anyStairs(PrepackagedPreset.stairs($facing, Bisected.Half.$half, shape = $shape))" } data.material.isSlab -> { data as Slab val type = data.type - if (type == Slab.Type.DOUBLE) return ".doubleSlab()" + if (type == Slab.Type.DOUBLE) return ".anyDoubleSlab()" - ".anySlab(PrepackagedPreset.slab($type))" + ".anySlab(PrepackagedPreset.slab(Slab.Type.$type))" } - data.material.isTerracotta -> ".terracotta()" - data.material.isGlass -> ".anyGlass()" data.material == Material.SEA_LANTERN -> ".seaLantern()" data.material == Material.STONE_BRICKS -> ".stoneBrick()" @@ -138,8 +148,9 @@ object StructureCreator : SLCommand() { data.material == Material.REDSTONE_BLOCK -> ".redstoneBlock()" data.material == Material.LAPIS_BLOCK -> ".lapisBlock()" - data.material == Wires.INPUT_COMPUTER_BLOCK -> ".wireInputComputer()" data.material == Material.FLETCHING_TABLE -> ".fluidInput()" + data.material == Material.LIGHTNING_ROD -> ".lightningRod()" + data.material == Wires.INPUT_COMPUTER_BLOCK -> ".powerInput()" data.material == Material.END_ROD -> ".endRod()" data.material == EXTRACTOR_TYPE -> ".extractor()" data.material == Material.HOPPER -> ".hopper()" @@ -158,13 +169,6 @@ object StructureCreator : SLCommand() { data.material == Material.MAGMA_BLOCK -> ".thrusterBlock()" data.material == Material.SEA_LANTERN -> ".thrusterBlock()" - data.material == Material.LIGHTNING_ROD -> ".lightningRod()" - - data.material.isGlassPane -> { - data as GlassPane - val faces = data.faces.map { RelativeFace[forwards, it] } - ".anyGlassPane(PrepackagedPreset.pane(${faces.joinToString { it.name }}))" - } else -> ".type(Material.${data.material.name})" } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 1e5a67071e..b90e91b3fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -2,9 +2,6 @@ package net.horizonsend.ion.server.features.multiblock.shape import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BARGE_REACTOR_CORE -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUISER_REACTOR_CORE -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING import net.horizonsend.ion.server.features.custom.items.CustomBlockItem @@ -15,7 +12,6 @@ import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.CONCRETE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.MATERIALS -import net.horizonsend.ion.server.miscellaneous.utils.STAINED_TERRACOTTA_TYPES import net.horizonsend.ion.server.miscellaneous.utils.TERRACOTTA_TYPES import net.horizonsend.ion.server.miscellaneous.utils.blockFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -26,7 +22,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.isButton -import net.horizonsend.ion.server.miscellaneous.utils.isConcrete import net.horizonsend.ion.server.miscellaneous.utils.isDaylightSensor import net.horizonsend.ion.server.miscellaneous.utils.isDoor import net.horizonsend.ion.server.miscellaneous.utils.isFroglight @@ -34,8 +29,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.isGlass import net.horizonsend.ion.server.miscellaneous.utils.isGlassPane import net.horizonsend.ion.server.miscellaneous.utils.isRedstoneLamp import net.horizonsend.ion.server.miscellaneous.utils.isSlab -import net.horizonsend.ion.server.miscellaneous.utils.isStainedGlass -import net.horizonsend.ion.server.miscellaneous.utils.isStainedGlassPane import net.horizonsend.ion.server.miscellaneous.utils.isStairs import net.horizonsend.ion.server.miscellaneous.utils.isTerracotta import net.horizonsend.ion.server.miscellaneous.utils.isTrapdoor @@ -294,24 +287,15 @@ class MultiblockShape { fun filteredTypes(alias: String, edit: BlockRequirement.() -> Unit = {}, filter: (Material) -> Boolean) = anyType(alias, MATERIALS.filter(filter), edit = edit) - fun carbyne() = anyType("any concrete", CONCRETE_TYPES) { setExample(Material.GRAY_CONCRETE.createBlockData()) } + // Start presets + fun anyConcrete() = anyType("any concrete block", CONCRETE_TYPES) { setExample(Material.GRAY_CONCRETE.createBlockData()) } + fun anyTerracotta() = anyType("any terracotta", TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } + fun anyGlass() = filteredTypes("any glass block", { setExample(Material.BLACK_STAINED_GLASS.createBlockData()) }) { it.isGlass } + fun anyGlassPane(edit: BlockRequirement.() -> Unit = {}) = filteredTypes("any stained glass pane", edit = edit) { it.isGlassPane } - fun terracotta() = anyType("any terracotta", TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } - fun stainedTerracotta() = anyType("any stained terracotta", STAINED_TERRACOTTA_TYPES) { setExample(Material.CYAN_TERRACOTTA.createBlockData()) } + fun stoneBrick() = type(Material.STONE_BRICKS) - fun glass() = type(Material.GLASS) - fun anvil() = type(Material.ANVIL) - fun bcReactorCore() = customBlock(BATTLECRUISER_REACTOR_CORE) - fun bargeReactorCore() = customBlock(BARGE_REACTOR_CORE) - fun cruiserReactorCore() = customBlock(CRUISER_REACTOR_CORE) - fun netheriteCasing() = customBlock(NETHERITE_CASING) - fun enrichedUraniumBlock() = customBlock(ENRICHED_URANIUM_BLOCK) - fun stainedGlass() = filteredTypes("any stained glass block") { it.isStainedGlass } - fun anyGlass() = filteredTypes("any glass block") { it.isGlass } fun seaLantern() = type(Material.SEA_LANTERN) - fun glassPane() = type(Material.GLASS_PANE) - fun stainedGlassPane() = filteredTypes("any stained glass pane") { it.isStainedGlassPane } - fun anyGlassPane(edit: BlockRequirement.() -> Unit = {}) = filteredTypes("any stained glass pane", edit = edit) { it.isGlassPane } fun anyStairs(edit: BlockRequirement.() -> Unit = { setExample(Material.STONE_BRICK_STAIRS.createBlockData()) }) = filteredTypes("any stair block", edit) { it.isStairs } @@ -341,7 +325,7 @@ class MultiblockShape { ) ) - fun anySlabOrStairs() = filteredTypes("any slab or stairs") { it.isSlab || it.isStairs } + fun anySlabOrStairs() = filteredTypes("any slab or stairs", { setExample(Material.STONE_BRICK_SLAB) }) { it.isSlab || it.isStairs } fun terracottaOrDoubleslab() { BlockRequirement( @@ -370,10 +354,7 @@ class MultiblockShape { ) } - fun concrete() = filteredTypes("any concrete block") { it.isConcrete } - fun sculkCatalyst() = type(Material.SCULK_CATALYST) - fun stoneBrick() = type(Material.STONE_BRICKS) fun ironBlock() = type(Material.IRON_BLOCK) fun goldBlock() = type(Material.GOLD_BLOCK) @@ -382,6 +363,13 @@ class MultiblockShape { fun emeraldBlock() = type(Material.EMERALD_BLOCK) fun redstoneBlock() = type(Material.REDSTONE_BLOCK) fun lapisBlock() = type(Material.LAPIS_BLOCK) + + fun titaniumBlock() = customBlock(CustomBlocks.TITANIUM_BLOCK) + fun aluminumBlock() = customBlock(CustomBlocks.ALUMINUM_BLOCK) + fun chetheriteBlock() = customBlock(CustomBlocks.CHETHERITE_BLOCK) + fun steelBlock() = customBlock(CustomBlocks.STEEL_BLOCK) + fun enrichedUraniumBlock() = customBlock(ENRICHED_URANIUM_BLOCK) + fun anyCopperVariant() = anyType( Material.COPPER_BLOCK, Material.EXPOSED_COPPER, @@ -401,7 +389,8 @@ class MultiblockShape { Material.WAXED_OXIDIZED_CUT_COPPER, alias = "any copper variant", ) - fun copperBlock() = anyType( + + fun anySolidCopperBlock() = anyType( Material.COPPER_BLOCK, Material.EXPOSED_COPPER, Material.WEATHERED_COPPER, @@ -412,7 +401,24 @@ class MultiblockShape { Material.WAXED_OXIDIZED_COPPER, alias = "any solid copper block" ) - fun copperGrate() = anyType( + + fun anyWaxedCopperBlock() = anyType( + Material.WAXED_COPPER_BLOCK, + Material.WAXED_EXPOSED_COPPER, + Material.WAXED_WEATHERED_COPPER, + Material.WAXED_OXIDIZED_COPPER, + alias = "any waxed solid copper block" + ) + + fun anyUnwaxedCopperBlock() = anyType( + Material.COPPER_BLOCK, + Material.EXPOSED_COPPER, + Material.WEATHERED_COPPER, + Material.OXIDIZED_COPPER, + alias = "any unwaxed solid copper block" + ) + + fun anyCopperGrate() = anyType( Material.COPPER_GRATE, Material.EXPOSED_COPPER_GRATE, Material.WEATHERED_COPPER_GRATE, @@ -421,9 +427,26 @@ class MultiblockShape { Material.WAXED_EXPOSED_COPPER_GRATE, Material.WAXED_WEATHERED_COPPER_GRATE, Material.WAXED_OXIDIZED_COPPER_GRATE, - alias = "any copper bulb" + alias = "any copper grate" + ) + + fun anyUnwaxedCopperGrate() = anyType( + Material.COPPER_GRATE, + Material.EXPOSED_COPPER_GRATE, + Material.WEATHERED_COPPER_GRATE, + Material.OXIDIZED_COPPER_GRATE, + alias = "any unwaxed copper grate" + ) + + fun anyWaxedCopperGrate() = anyType( + Material.WAXED_COPPER_GRATE, + Material.WAXED_EXPOSED_COPPER_GRATE, + Material.WAXED_WEATHERED_COPPER_GRATE, + Material.WAXED_OXIDIZED_COPPER_GRATE, + alias = "any waxed copper grate" ) - fun copperBulb() = anyType( + + fun anyCopperBulb() = anyType( Material.COPPER_BULB, Material.EXPOSED_COPPER_BULB, Material.WEATHERED_COPPER_BULB, @@ -434,41 +457,50 @@ class MultiblockShape { Material.WAXED_OXIDIZED_COPPER_BULB, alias = "any copper bulb" ) - fun fluidInput() = type(Material.FLETCHING_TABLE) - - fun titaniumBlock() = customBlock(CustomBlocks.TITANIUM_BLOCK) - fun aluminumBlock() = customBlock(CustomBlocks.ALUMINUM_BLOCK) - fun chetheriteBlock() = customBlock(CustomBlocks.CHETHERITE_BLOCK) - fun steelBlock() = customBlock(CustomBlocks.STEEL_BLOCK) - fun wireInputComputer() = type(Wires.INPUT_COMPUTER_BLOCK) - fun redstoneLamp() = filteredTypes("redstone lamp") { it.isRedstoneLamp } + fun anyWaxedCopperBulb() = anyType( + Material.WAXED_COPPER_BULB, + Material.WAXED_EXPOSED_COPPER_BULB, + Material.WAXED_WEATHERED_COPPER_BULB, + Material.WAXED_OXIDIZED_COPPER_BULB, + alias = "any waxed copper bulb" + ) - fun daylightSensor() = filteredTypes("daylight sensor") { it.isDaylightSensor } - fun craftingTable() = type(Material.CRAFTING_TABLE) + fun anyUnwaxedCopperBulb() = anyType( + Material.COPPER_BULB, + Material.EXPOSED_COPPER_BULB, + Material.WEATHERED_COPPER_BULB, + Material.OXIDIZED_COPPER_BULB, + alias = "any unwaxed copper bulb" + ) + fun fluidInput() = type(Material.FLETCHING_TABLE) + fun powerInput() = type(Wires.INPUT_COMPUTER_BLOCK) fun extractor() = type(EXTRACTOR_TYPE) - fun glowstone() = type(Material.GLOWSTONE) - fun sponge() = anyType(Material.SPONGE, Material.WET_SPONGE, alias = "sponge") fun endRod() = type(Material.END_ROD) - fun grindstone() = type(Material.GRINDSTONE) + fun lightningRod() = type(Material.LIGHTNING_ROD) fun hopper() = type(Material.HOPPER) + fun anyPipedInventory() = filteredTypes("any container block", edit = { setExample(Material.CHEST.createBlockData()) }) { Pipes.isPipedInventory(it) } + fun dispenser() = type(Material.DISPENSER) + + fun netheriteCasing() = customBlock(NETHERITE_CASING) + + fun redstoneLamp() = filteredTypes("redstone lamp") { it.isRedstoneLamp } + fun daylightSensor() = filteredTypes("daylight sensor") { it.isDaylightSensor } + + fun grindstone() = type(Material.GRINDSTONE) fun anyDoor() = filteredTypes("any door", edit = { setExample(Material.OAK_DOOR.createBlockData()) }) { it.isDoor } fun anyButton() = filteredTypes("any button") { it.isButton } - fun anyPipedInventory() = filteredTypes("any container block", edit = { setExample(Material.CHEST.createBlockData()) }) { Pipes.isPipedInventory(it) } - fun pistonBase() = type(Material.PISTON) fun pistonHead() = type(Material.PISTON_HEAD) fun furnace() = type(Material.FURNACE) - fun dispenser() = type(Material.DISPENSER) fun lodestone() = type(Material.LODESTONE) - fun noteBlock() = type(Material.NOTE_BLOCK) fun anyTrapdoor() = filteredTypes("any trapdoor") { it.isTrapdoor } fun anyFroglight() = filteredTypes("any froglight") { it.isFroglight } @@ -483,8 +515,6 @@ class MultiblockShape { alias = "any light block" ) - fun lightningRod() = type(Material.LIGHTNING_ROD) - fun machineFurnace() = complete(BlockRequirement( alias = "furnace", example = Material.FURNACE.createBlockData(), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 2e9792e463..dcc0ec27c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -21,7 +21,7 @@ object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock Unit) : Multiblock() { + override fun matchesUndetectedSign(sign: Sign): Boolean { + return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[reactor]", ignoreCase = true) + } + + override fun MultiblockShape.buildStructure() { + z(+0) { + y(-1) { + x(-1).anySlab() + x(+0).anyStairs() + x(+1).anySlab() + } + y(+0) { + x(-2).anyStairs() + x(-1).ironBlock() + x(+0).redstoneBlock() + x(+1).ironBlock() + x(+2).anyStairs() + } + y(+1) { + x(-2).ironBlock() + x(-1).anyGlassPane() + x(+0).anyGlass() + x(+1).anyGlassPane() + x(+2).ironBlock() + } + y(+2) { + x(-2).anyStairs() + x(-1).ironBlock() + x(+0).redstoneBlock() + x(+1).ironBlock() + x(+2).anyStairs() + } + y(+3) { + x(-1).anySlab() + x(+0).anyStairs() + x(+1).anySlab() + } + } + z(+1) { + y(-1) { + x(-2).anySlab() + x(-1).titaniumBlock() + x(+0).anyStairs() + x(+1).titaniumBlock() + x(+2).anySlab() + } + y(+0) { + x(-2).ironBlock() + x(-1).emeraldBlock() + x(+0).seaLantern() + x(+1).emeraldBlock() + x(+2).ironBlock() + } + y(+1) { + x(-2).anyGlassPane() + x(-1).seaLantern() + x(+0).endRod() + x(+1).seaLantern() + x(+2).anyGlassPane() + } + y(+2) { + x(-2).ironBlock() + x(-1).emeraldBlock() + x(+0).seaLantern() + x(+1).emeraldBlock() + x(+2).ironBlock() + } + y(+3) { + x(-2).anySlab() + x(-1).titaniumBlock() + x(+0).anyStairs() + x(+1).titaniumBlock() + x(+2).anySlab() + } + } + z(+2) { + y(-1) { + x(-2).anyStairs() + x(-1).anyStairs() + x(+0).anyGlass() + x(+1).anyStairs() + x(+2).anyStairs() + } + y(+0) { + x(-2).ironBlock() + x(-1).seaLantern() + x(+0).grindstone() + x(+1).seaLantern() + x(+2).ironBlock() + } + y(+1) { + x(-2).anyGlass() + x(-1).endRod() + x(+0).core() + x(+1).endRod() + x(+2).anyGlass() + } + y(+2) { + x(-2).ironBlock() + x(-1).seaLantern() + x(+0).grindstone() + x(+1).seaLantern() + x(+2).ironBlock() + } + y(+3) { + x(-2).anyStairs() + x(-1).anyStairs() + x(+0).anyGlass() + x(+1).anyStairs() + x(+2).anyStairs() + } + } + z(+3) { + y(-1) { + x(-2).anySlab() + x(-1).titaniumBlock() + x(+0).anyStairs() + x(+1).titaniumBlock() + x(+2).anySlab() + } + y(+0) { + x(-2).ironBlock() + x(-1).emeraldBlock() + x(+0).seaLantern() + x(+1).emeraldBlock() + x(+2).ironBlock() + } + y(+1) { + x(-2).anyGlassPane() + x(-1).seaLantern() + x(+0).endRod() + x(+1).seaLantern() + x(+2).anyGlassPane() + } + y(+2) { + x(-2).ironBlock() + x(-1).emeraldBlock() + x(+0).seaLantern() + x(+1).emeraldBlock() + x(+2).ironBlock() + } + y(+3) { + x(-2).anySlab() + x(-1).titaniumBlock() + x(+0).anyStairs() + x(+1).titaniumBlock() + x(+2).anySlab() + } + } + z(+4) { + y(-1) { + x(-1).anySlab() + x(+0).anyStairs() + x(+1).anySlab() + } + y(+0) { + x(-2).anyStairs() + x(-1).ironBlock() + x(+0).redstoneBlock() + x(+1).ironBlock() + x(+2).anyStairs() + } + y(+1) { + x(-2).ironBlock() + x(-1).anyGlassPane() + x(+0).anyGlass() + x(+1).anyGlassPane() + x(+2).ironBlock() + } + y(+2) { + x(-2).anyStairs() + x(-1).ironBlock() + x(+0).redstoneBlock() + x(+1).ironBlock() + x(+2).anyStairs() + } + y(+3) { + x(-1).anySlab() + x(+0).anyStairs() + x(+1).anySlab() + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt index a54b1df8f2..3e883097c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt @@ -1,13 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist -import net.horizonsend.ion.common.utils.text.plainText -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import org.bukkit.Material -import org.bukkit.block.Sign -import org.bukkit.block.sign.Side +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BARGE_REACTOR_CORE -object BargeReactorMultiBlock : Multiblock() { +object BargeReactorMultiBlock : AbstractReactorCore({ customBlock(BARGE_REACTOR_CORE) }) { override val name: String = "bargereactor" override val signText = createSignText( "&7-=[&c==&a==&b==&7]=-", @@ -15,188 +10,4 @@ object BargeReactorMultiBlock : Multiblock() { "&7&cFusion Reactor&7", "&7-=[&c==&a==&b==&7]=-" ) - - override fun matchesUndetectedSign(sign: Sign): Boolean { - return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[reactor]", ignoreCase = true) - } - - override fun MultiblockShape.buildStructure() { - z(+0) { - y(-1) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - y(+0) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+1) { - x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - x(+2).ironBlock() - } - y(+2) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+3) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - } - z(+1) { - y(-1) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - y(+0) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlassPane() - x(-1).seaLantern() - x(+0).endRod() - x(+1).seaLantern() - x(+2).anyGlassPane() - } - y(+2) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+3) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - } - z(+2) { - y(-1) { - x(-2).anyStairs() - x(-1).anyStairs() - x(+0).anyGlass() - x(+1).anyStairs() - x(+2).anyStairs() - } - y(+0) { - x(-2).ironBlock() - x(-1).seaLantern() - x(+0).type(Material.GRINDSTONE) - x(+1).seaLantern() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlass() - x(-1).endRod() - x(+0).bargeReactorCore() - x(+1).endRod() - x(+2).anyGlass() - } - y(+2) { - x(-2).ironBlock() - x(-1).seaLantern() - x(+0).type(Material.GRINDSTONE) - x(+1).seaLantern() - x(+2).ironBlock() - } - y(+3) { - x(-2).anyStairs() - x(-1).anyStairs() - x(+0).anyGlass() - x(+1).anyStairs() - x(+2).anyStairs() - } - } - z(+3) { - y(-1) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - y(+0) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlassPane() - x(-1).seaLantern() - x(+0).endRod() - x(+1).seaLantern() - x(+2).anyGlassPane() - } - y(+2) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+3) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - } - z(+4) { - y(-1) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - y(+0) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+1) { - x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - x(+2).ironBlock() - } - y(+2) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+3) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt index 2e244df8bb..14d2b90115 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt @@ -1,13 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist -import net.horizonsend.ion.common.utils.text.plainText -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import org.bukkit.Material -import org.bukkit.block.Sign -import org.bukkit.block.sign.Side +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUISER_REACTOR_CORE -object BattleCruiserReactorMultiblock : Multiblock() { +object BattleCruiserReactorMultiblock : AbstractReactorCore({ customBlock(BATTLECRUISER_REACTOR_CORE) }) { override val name: String = "bcreactor" override val signText = createSignText( "&7-=[&c==&a==&b==&7]=-", @@ -15,189 +10,5 @@ object BattleCruiserReactorMultiblock : Multiblock() { "&7&cFusion Reactor&7", "&7-=[&c==&a==&b==&7]=-" ) - - override fun matchesUndetectedSign(sign: Sign): Boolean { - return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[reactor]", ignoreCase = true) - } - - override fun MultiblockShape.buildStructure() { - z(+0) { - y(-1) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - y(+0) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+1) { - x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - x(+2).ironBlock() - } - y(+2) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+3) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - } - z(+1) { - y(-1) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - y(+0) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlassPane() - x(-1).seaLantern() - x(+0).endRod() - x(+1).seaLantern() - x(+2).anyGlassPane() - } - y(+2) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+3) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - } - z(+2) { - y(-1) { - x(-2).anyStairs() - x(-1).anyStairs() - x(+0).anyGlass() - x(+1).anyStairs() - x(+2).anyStairs() - } - y(+0) { - x(-2).ironBlock() - x(-1).seaLantern() - x(+0).type(Material.GRINDSTONE) - x(+1).seaLantern() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlass() - x(-1).endRod() - x(+0).bcReactorCore() - x(+1).endRod() - x(+2).anyGlass() - } - y(+2) { - x(-2).ironBlock() - x(-1).seaLantern() - x(+0).type(Material.GRINDSTONE) - x(+1).seaLantern() - x(+2).ironBlock() - } - y(+3) { - x(-2).anyStairs() - x(-1).anyStairs() - x(+0).anyGlass() - x(+1).anyStairs() - x(+2).anyStairs() - } - } - z(+3) { - y(-1) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - y(+0) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlassPane() - x(-1).seaLantern() - x(+0).endRod() - x(+1).seaLantern() - x(+2).anyGlassPane() - } - y(+2) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+3) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - } - z(+4) { - y(-1) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - y(+0) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+1) { - x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - x(+2).ironBlock() - } - y(+2) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+3) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt index d361b12ef5..f4d4a80c10 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt @@ -1,13 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist -import net.horizonsend.ion.common.utils.text.plainText -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import org.bukkit.Material -import org.bukkit.block.Sign -import org.bukkit.block.sign.Side +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE -object CruiserReactorMultiblock : Multiblock() { +object CruiserReactorMultiblock : AbstractReactorCore({ customBlock(CRUISER_REACTOR_CORE) }) { override val name: String = "cruiserreactor" override val signText = createSignText( @@ -16,189 +11,5 @@ object CruiserReactorMultiblock : Multiblock() { "&7&cFusion Reactor&7", "&7-=[&c==&a==&b==&7]=-" ) - - override fun matchesUndetectedSign(sign: Sign): Boolean { - return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[reactor]", ignoreCase = true) - } - - override fun MultiblockShape.buildStructure() { - z(+0) { - y(-1) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - y(+0) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+1) { - x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - x(+2).ironBlock() - } - y(+2) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+3) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - } - z(+1) { - y(-1) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - y(+0) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlassPane() - x(-1).seaLantern() - x(+0).endRod() - x(+1).seaLantern() - x(+2).anyGlassPane() - } - y(+2) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+3) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - } - z(+2) { - y(-1) { - x(-2).anyStairs() - x(-1).anyStairs() - x(+0).anyGlass() - x(+1).anyStairs() - x(+2).anyStairs() - } - y(+0) { - x(-2).ironBlock() - x(-1).seaLantern() - x(+0).type(Material.GRINDSTONE) - x(+1).seaLantern() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlass() - x(-1).endRod() - x(+0).cruiserReactorCore() - x(+1).endRod() - x(+2).anyGlass() - } - y(+2) { - x(-2).ironBlock() - x(-1).seaLantern() - x(+0).type(Material.GRINDSTONE) - x(+1).seaLantern() - x(+2).ironBlock() - } - y(+3) { - x(-2).anyStairs() - x(-1).anyStairs() - x(+0).anyGlass() - x(+1).anyStairs() - x(+2).anyStairs() - } - } - z(+3) { - y(-1) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - y(+0) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+1) { - x(-2).anyGlassPane() - x(-1).seaLantern() - x(+0).endRod() - x(+1).seaLantern() - x(+2).anyGlassPane() - } - y(+2) { - x(-2).ironBlock() - x(-1).emeraldBlock() - x(+0).seaLantern() - x(+1).emeraldBlock() - x(+2).ironBlock() - } - y(+3) { - x(-2).anySlab() - x(-1).titaniumBlock() - x(+0).anyStairs() - x(+1).titaniumBlock() - x(+2).anySlab() - } - } - z(+4) { - y(-1) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - y(+0) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+1) { - x(-2).ironBlock() - x(-1).anyGlassPane() - x(+0).anyGlass() - x(+1).anyGlassPane() - x(+2).ironBlock() - } - y(+2) { - x(-2).anyStairs() - x(-1).ironBlock() - x(+0).redstoneBlock() - x(+1).ironBlock() - x(+2).anyStairs() - } - y(+3) { - x(-1).anySlab() - x(+0).anyStairs() - x(+1).anySlab() - } - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt index b14d874a90..ff6871d221 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt @@ -50,9 +50,9 @@ object AmplifiedGravityWellMultiblock : GravityWellMultiblock() { y(+0) { x(-2).type(Material.IRON_BARS) - x(-1).glassPane() - x(+0).glassPane() - x(+1).glassPane() + x(-1).anyGlassPane() + x(+0).anyGlassPane() + x(+1).anyGlassPane() x(+2).type(Material.IRON_BARS) } @@ -75,11 +75,11 @@ object AmplifiedGravityWellMultiblock : GravityWellMultiblock() { } y(+0) { - x(-2).glass() + x(-2).anyGlass() x(-1).anyGlassPane() x(+0).emeraldBlock() x(+1).anyGlassPane() - x(+2).glass() + x(+2).anyGlass() } y(+1) { @@ -102,9 +102,9 @@ object AmplifiedGravityWellMultiblock : GravityWellMultiblock() { y(+0) { x(-2).type(Material.IRON_BARS) - x(-1).glassPane() - x(+0).glassPane() - x(+1).glassPane() + x(-1).anyGlassPane() + x(+0).anyGlassPane() + x(+1).anyGlassPane() x(+2).type(Material.IRON_BARS) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt index e524518387..35b2208636 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt @@ -20,7 +20,7 @@ object HyperdriveMultiblockClass1 : HyperdriveMultiblock() { z(+0) { y(-1) { - x(+0).wireInputComputer() + x(+0).powerInput() } y(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt index 02739fdcf4..7d882124cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt @@ -20,7 +20,7 @@ object HyperdriveMultiblockClass2 : HyperdriveMultiblock() { z(+0) { y(-1) { - x(+0).wireInputComputer() + x(+0).powerInput() } y(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt index fcca3693c8..f8220c7f85 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt @@ -20,7 +20,7 @@ object HyperdriveMultiblockClass3 : HyperdriveMultiblock() { z(+0) { y(-1) { - x(0).wireInputComputer() + x(0).powerInput() } for (y in 0..1) y(y) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt index b9c5e8b3f9..75ed495ef5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt @@ -20,7 +20,7 @@ object HyperdriveMultiblockClass4 : HyperdriveMultiblock() { z(+0) { y(-1) { - x(0).wireInputComputer() + x(0).powerInput() } for (y in 0..1) y(y) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt index 853c22e73e..aa273404dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier1.kt @@ -38,7 +38,7 @@ object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { z(+0) { y(-1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -50,7 +50,7 @@ object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { y(+1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -72,9 +72,9 @@ object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { x(+1).titaniumBlock() } y(+1) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+2) { x(-1).anyGlassPane() @@ -98,7 +98,7 @@ object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { y(+1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -118,7 +118,7 @@ object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { z(+0) { y(-1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -130,7 +130,7 @@ object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { y(+1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -152,9 +152,9 @@ object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { x(+1).titaniumBlock() } y(+1) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+2) { x(-1).anyGlassPane() @@ -178,7 +178,7 @@ object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { y(+1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -199,7 +199,7 @@ object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { z(+0) { y(+1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -211,7 +211,7 @@ object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { y(-1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -233,9 +233,9 @@ object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { x(+1).titaniumBlock() } y(-1) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(-2) { x(-1).anyGlassPane() @@ -259,7 +259,7 @@ object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { y(-1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -280,7 +280,7 @@ object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { z(+0) { y(+1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -292,7 +292,7 @@ object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { y(-1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -314,9 +314,9 @@ object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { x(+1).titaniumBlock() } y(-1) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(-2) { x(-1).anyGlassPane() @@ -340,7 +340,7 @@ object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { y(-1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -361,7 +361,7 @@ object MiningLaserMultiblockTier1Side : MiningLaserMultiblockTier1() { z(+0) { y(-1) { x(+1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(-1).anyPipedInventory() } @@ -401,19 +401,19 @@ object MiningLaserMultiblockTier1Side : MiningLaserMultiblockTier1() { z(+2) { y(-1) { x(+1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } y(+0) { - x(+1).terracotta() + x(+1).anyTerracotta() x(+0).emeraldBlock() - x(-1).terracotta() + x(-1).anyTerracotta() } y(+1) { x(+1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } } @@ -445,7 +445,7 @@ object MiningLaserMultiblockTier1SideMirrored : MiningLaserMultiblockTier1() { z(+0) { y(-1) { x(+1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(-1).ironBlock() } @@ -485,19 +485,19 @@ object MiningLaserMultiblockTier1SideMirrored : MiningLaserMultiblockTier1() { z(+2) { y(-1) { x(+1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } y(+0) { - x(+1).terracotta() + x(+1).anyTerracotta() x(+0).emeraldBlock() - x(-1).terracotta() + x(-1).anyTerracotta() } y(+1) { x(+1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt index afce2e530f..2d644e89a8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt @@ -36,7 +36,7 @@ object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { z(+0) { y(-1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -58,7 +58,7 @@ object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { y(+3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -93,9 +93,9 @@ object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { } y(+3) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+4) { @@ -130,7 +130,7 @@ object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { y(+3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -152,7 +152,7 @@ object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { z(+0) { y(-1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -174,7 +174,7 @@ object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { y(+3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -209,9 +209,9 @@ object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { } y(+3) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+4) { @@ -246,7 +246,7 @@ object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { y(+3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -267,7 +267,7 @@ object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { z(+0) { y(+1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -289,7 +289,7 @@ object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { y(-3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -324,9 +324,9 @@ object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { } y(-3) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(-4) { @@ -361,7 +361,7 @@ object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { y(-3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -382,7 +382,7 @@ object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { z(+0) { y(+1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -404,7 +404,7 @@ object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { y(-3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -439,9 +439,9 @@ object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { } y(-3) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(-4) { @@ -476,7 +476,7 @@ object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { y(-3) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } @@ -497,7 +497,7 @@ object MiningLaserMultiblockTier2Side : MiningLaserMultiblockTier2() { z(+0) { y(-1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -572,19 +572,19 @@ object MiningLaserMultiblockTier2Side : MiningLaserMultiblockTier2() { z(+4) { y(-1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } y(+0) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } z(+5) { @@ -617,7 +617,7 @@ object MiningLaserMultiblockTier2SideMirrored : MiningLaserMultiblockTier2() { z(+0) { y(-1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -692,19 +692,19 @@ object MiningLaserMultiblockTier2SideMirrored : MiningLaserMultiblockTier2() { z(+4) { y(-1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } y(+0) { - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).emeraldBlock() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+1) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } z(+5) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt index f99960e1dd..b0caed8531 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt @@ -36,7 +36,7 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { z(+0) { y(-1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -66,7 +66,7 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -114,9 +114,9 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -163,11 +163,11 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { } y(+4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).emeraldBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(+5) { @@ -220,9 +220,9 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -262,7 +262,7 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -279,7 +279,7 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { z(+0) { y(-1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -309,7 +309,7 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -357,9 +357,9 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -406,11 +406,11 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { } y(+4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).emeraldBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(+5) { @@ -463,9 +463,9 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -505,7 +505,7 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -522,7 +522,7 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { z(+0) { y(+1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -552,7 +552,7 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -600,9 +600,9 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -649,11 +649,11 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { } y(-4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).emeraldBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(-5) { @@ -706,9 +706,9 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -748,7 +748,7 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -765,7 +765,7 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { z(+0) { y(+1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -795,7 +795,7 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -843,9 +843,9 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -892,11 +892,11 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { } y(-4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).emeraldBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(-5) { @@ -949,9 +949,9 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -991,7 +991,7 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -1009,7 +1009,7 @@ object MiningLaserMultiblockTier3Side : MiningLaserMultiblockTier3() { y(-1) { x(-2).anyStairs() x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() } y(+0) { @@ -1187,35 +1187,35 @@ object MiningLaserMultiblockTier3Side : MiningLaserMultiblockTier3() { z(+5) { y(-1) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() } y(+0) { x(-3).anyStairs() - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } y(+1) { - x(-3).terracotta() + x(-3).anyTerracotta() x(-2).anyWall() x(-1).emeraldBlock() x(+0).anyWall() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+2) { x(-3).anyStairs() - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } y(+3) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() } @@ -1248,7 +1248,7 @@ object MiningLaserMultiblockTier3SideMirrored : MiningLaserMultiblockTier3() { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() x(+2).anyStairs() } @@ -1428,35 +1428,35 @@ object MiningLaserMultiblockTier3SideMirrored : MiningLaserMultiblockTier3() { z(+5) { y(-1) { x(+2).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+0).anyStairs() } y(+0) { x(+3).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() x(+1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } y(+1) { - x(+3).terracotta() + x(+3).anyTerracotta() x(+2).anyWall() x(+1).emeraldBlock() x(+0).anyWall() - x(-1).terracotta() + x(-1).anyTerracotta() } y(+2) { x(+3).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() x(+1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } y(+3) { x(+2).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+0).anyStairs() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt index eb617a92cf..29d9113265 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt @@ -35,7 +35,7 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { z(+0) { y(-1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -65,7 +65,7 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -113,9 +113,9 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -162,11 +162,11 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { } y(+4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).enrichedUraniumBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(+5) { @@ -219,9 +219,9 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -261,7 +261,7 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -278,7 +278,7 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { z(+0) { y(-1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -308,7 +308,7 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -356,9 +356,9 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -405,11 +405,11 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { } y(+4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).enrichedUraniumBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(+5) { @@ -462,9 +462,9 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { y(+4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -504,7 +504,7 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { y(+4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -521,7 +521,7 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { z(+0) { y(+1) { x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() x(+1).ironBlock() } @@ -551,7 +551,7 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -599,9 +599,9 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -648,11 +648,11 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { } y(-4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).enrichedUraniumBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(-5) { @@ -705,9 +705,9 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -747,7 +747,7 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -764,7 +764,7 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { z(+0) { y(+1) { x(-1).ironBlock() - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() } @@ -794,7 +794,7 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -842,9 +842,9 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -891,11 +891,11 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { } y(-4) { - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyStairs() x(+0).enrichedUraniumBlock() x(+1).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() } y(-5) { @@ -948,9 +948,9 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { y(-4) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+2).anyStairs() } @@ -990,7 +990,7 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { y(-4) { x(-1).anyStairs() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } } @@ -1008,7 +1008,7 @@ object MiningLaserMultiblockTier4Side : MiningLaserMultiblockTier4() { y(-1) { x(-2).anyStairs() x(-1).anyPipedInventory() - x(+0).noteBlock() + x(+0).powerInput() } y(+0) { @@ -1185,35 +1185,35 @@ object MiningLaserMultiblockTier4Side : MiningLaserMultiblockTier4() { z(+5) { y(-1) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() } y(+0) { x(-3).anyStairs() - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } y(+1) { - x(-3).terracotta() + x(-3).anyTerracotta() x(-2).anyWall() x(-1).enrichedUraniumBlock() x(+0).anyWall() - x(+1).terracotta() + x(+1).anyTerracotta() } y(+2) { x(-3).anyStairs() - x(-2).terracotta() + x(-2).anyTerracotta() x(-1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(+1).anyStairs() } y(+3) { x(-2).anyStairs() - x(-1).terracotta() + x(-1).anyTerracotta() x(+0).anyStairs() } @@ -1246,7 +1246,7 @@ object MiningLaserMultiblockTier4SideMirrored : MiningLaserMultiblockTier4() { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { - x(+0).noteBlock() + x(+0).powerInput() x(+1).anyPipedInventory() x(+2).anyStairs() } @@ -1425,35 +1425,35 @@ object MiningLaserMultiblockTier4SideMirrored : MiningLaserMultiblockTier4() { z(+5) { y(-1) { x(+2).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+0).anyStairs() } y(+0) { x(+3).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() x(+1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } y(+1) { - x(+3).terracotta() + x(+3).anyTerracotta() x(+2).anyWall() x(+1).enrichedUraniumBlock() x(+0).anyWall() - x(-1).terracotta() + x(-1).anyTerracotta() } y(+2) { x(+3).anyStairs() - x(+2).terracotta() + x(+2).anyTerracotta() x(+1).anyWall() - x(+0).terracotta() + x(+0).anyTerracotta() x(-1).anyStairs() } y(+3) { x(+2).anyStairs() - x(+1).terracotta() + x(+1).anyTerracotta() x(+0).anyStairs() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt index 7f84156b69..ff73c0064d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt @@ -14,6 +14,6 @@ object PulseCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock z(z) { y(-1) { - x(+0).stainedGlass() + x(+0).anyGlass() } y(+0) { - x(-1).stainedGlass() + x(-1).anyGlass() x(+0).redstoneBlock() - x(+1).stainedGlass() + x(+1).anyGlass() } y(+1) { - x(+0).stainedGlass() + x(+0).anyGlass() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt index 9a558d1bc5..1bcad3d546 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt @@ -23,7 +23,7 @@ object PhaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock Unit = { +// example = Material.STONE_BRICK_WALL.createBlockData() +// addPlacementModification { multiblockDirection: BlockFace, pane: BlockData -> +// pane as MultipleFacing +// face.forEach { pane.setFace(it[multiblockDirection], true) } +// } +// } + fun slab(type: Slab.Type): BlockRequirement.() -> Unit = { example = Material.STONE_BRICK_SLAB.createBlockData() addPlacementModification { multiblockDirection: BlockFace, slab: BlockData -> From e83278831b92e5e3c96fe18e1b3c31351adc1d01 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 10:47:03 -0600 Subject: [PATCH 337/500] Add trapdoor preset --- .../ion/server/command/admin/StructureCreator.kt | 7 ++++++- .../features/multiblock/shape/MultiblockShape.kt | 2 +- .../features/multiblock/util/PrepackagedPreset.kt | 14 +++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index 955ba9388f..582ee3e014 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -27,6 +27,7 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.GlassPane import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Stairs +import org.bukkit.block.data.type.TrapDoor import org.bukkit.entity.Player @CommandPermission("ion.admin.structurecreator") @@ -156,7 +157,11 @@ object StructureCreator : SLCommand() { data.material == Material.HOPPER -> ".hopper()" data.material == Material.DISPENSER -> ".dispenser()" - data.material.isTrapdoor -> ".anyTrapdoor()" + data.material.isTrapdoor -> { + data as TrapDoor + val facing = RelativeFace[forwards, data.facing] + ".anyTrapdoor(PrepackagedPreset.trapdoor(Bisected.Half.${data.half}, RelativeFace.$facing, ${data.isPowered}, ${data.isOpen}))" + } data.material == Material.SPONGE -> ".sponge()" data.material == Material.WET_SPONGE -> ".sponge()" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index b90e91b3fc..00d81e1a03 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -501,7 +501,7 @@ class MultiblockShape { fun furnace() = type(Material.FURNACE) fun lodestone() = type(Material.LODESTONE) - fun anyTrapdoor() = filteredTypes("any trapdoor") { it.isTrapdoor } + fun anyTrapdoor(edit: BlockRequirement.() -> Unit = {}) = filteredTypes("any trapdoor", edit) { it.isTrapdoor } fun anyFroglight() = filteredTypes("any froglight") { it.isFroglight } fun thrusterBlock() = anyType( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt index 09650ed151..176664a06e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt @@ -9,6 +9,7 @@ import org.bukkit.block.data.BlockData import org.bukkit.block.data.MultipleFacing import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Stairs +import org.bukkit.block.data.type.TrapDoor object PrepackagedPreset { fun stairs(face: RelativeFace, half: Bisected.Half, shape: Stairs.Shape): BlockRequirement.() -> Unit = { @@ -39,7 +40,7 @@ object PrepackagedPreset { fun slab(type: Slab.Type): BlockRequirement.() -> Unit = { example = Material.STONE_BRICK_SLAB.createBlockData() - addPlacementModification { multiblockDirection: BlockFace, slab: BlockData -> + addPlacementModification { _: BlockFace, slab: BlockData -> slab as Slab slab.type = type } @@ -48,4 +49,15 @@ object PrepackagedPreset { fun blockUpdate(): BlockRequirement.() -> Unit = { blockUpdate = true } + + fun trapdoor(half: Bisected.Half, facing: RelativeFace, powered: Boolean, open: Boolean): BlockRequirement.() -> Unit = { + example = Material.OAK_TRAPDOOR.createBlockData() + addPlacementModification { structureDirection, data -> + data as TrapDoor + data.isOpen = open + data.isPowered = powered + data.half = half + data.facing = facing[structureDirection] + } + } } From 0ad95860c583ce8453f74ae47cf512f107b211d4 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 10:52:21 -0600 Subject: [PATCH 338/500] Add grindstone preset --- .../ion/server/command/admin/StructureCreator.kt | 7 +++++++ .../features/multiblock/shape/MultiblockShape.kt | 6 ++++-- .../features/multiblock/util/PrepackagedPreset.kt | 9 +++++++++ .../miscellaneous/utils/coordinates/RelativeFace.kt | 11 +++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index 582ee3e014..a4f418e4ef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -25,6 +25,7 @@ import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.GlassPane +import org.bukkit.block.data.type.Grindstone import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Stairs import org.bukkit.block.data.type.TrapDoor @@ -157,6 +158,12 @@ object StructureCreator : SLCommand() { data.material == Material.HOPPER -> ".hopper()" data.material == Material.DISPENSER -> ".dispenser()" + data.material == Material.GRINDSTONE -> { + data as Grindstone + val facing = RelativeFace[forwards, data.facing] + ".dispenser(PrepackagedPreset.simpleDirectional(RelativeFace.$facing, example = Material.GRINDSTONE.createBlockData()))" + } + data.material.isTrapdoor -> { data as TrapDoor val facing = RelativeFace[forwards, data.facing] diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 00d81e1a03..32ce48ae00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -221,7 +221,7 @@ class MultiblockShape { class RequirementBuilder(val shape: MultiblockShape, val right: Int, val upward: Int, val inward: Int) { private fun complete(requirement: BlockRequirement) = shape.addRequirement(right, upward, inward, requirement) - fun type(type: Material) { + fun type(type: Material, edit: BlockRequirement.() -> Unit = {}) { val requirement = BlockRequirement( alias = type.toString(), example = type.createBlockData(), @@ -235,6 +235,8 @@ class MultiblockShape { ) complete(requirement) + + edit(requirement) } fun anyType(vararg types: Material, alias: String, edit: BlockRequirement.() -> Unit = {}) { @@ -491,7 +493,7 @@ class MultiblockShape { fun redstoneLamp() = filteredTypes("redstone lamp") { it.isRedstoneLamp } fun daylightSensor() = filteredTypes("daylight sensor") { it.isDaylightSensor } - fun grindstone() = type(Material.GRINDSTONE) + fun grindstone(edit: BlockRequirement.() -> Unit = {}) = type(Material.GRINDSTONE, edit) fun anyDoor() = filteredTypes("any door", edit = { setExample(Material.OAK_DOOR.createBlockData()) }) { it.isDoor } fun anyButton() = filteredTypes("any button") { it.isButton } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt index 176664a06e..a7cb194bff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/PrepackagedPreset.kt @@ -6,6 +6,7 @@ import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.data.Bisected import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Directional import org.bukkit.block.data.MultipleFacing import org.bukkit.block.data.type.Slab import org.bukkit.block.data.type.Stairs @@ -60,4 +61,12 @@ object PrepackagedPreset { data.facing = facing[structureDirection] } } + + fun simpleDirectional(face: RelativeFace, example: BlockData? = null): BlockRequirement.() -> Unit = { + example?.let { this.example = it } + addPlacementModification { blockFace, blockData -> + blockData as Directional + blockData.facing = face[blockFace] + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt index de1e5e034c..a86184d529 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/RelativeFace.kt @@ -24,8 +24,19 @@ enum class RelativeFace { override fun get(face: BlockFace): BlockFace { return face.leftFace } + }, + UP { + override fun get(face: BlockFace): BlockFace { + return BlockFace.UP + } + }, + DOWN { + override fun get(face: BlockFace): BlockFace { + return BlockFace.DOWN + } }; + abstract operator fun get(face: BlockFace): BlockFace companion object { From c0ad66f4f9f19f943987ec249688e7a67fcc551b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 10:55:49 -0600 Subject: [PATCH 339/500] Add lightning rod, end rod --- .../server/command/admin/StructureCreator.kt | 17 ++++++++++++++--- .../multiblock/shape/MultiblockShape.kt | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index a4f418e4ef..b15f1699b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -24,6 +24,7 @@ import net.kyori.adventure.text.event.ClickEvent import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.data.BlockData +import org.bukkit.block.data.Directional import org.bukkit.block.data.type.GlassPane import org.bukkit.block.data.type.Grindstone import org.bukkit.block.data.type.Slab @@ -151,9 +152,7 @@ object StructureCreator : SLCommand() { data.material == Material.LAPIS_BLOCK -> ".lapisBlock()" data.material == Material.FLETCHING_TABLE -> ".fluidInput()" - data.material == Material.LIGHTNING_ROD -> ".lightningRod()" data.material == Wires.INPUT_COMPUTER_BLOCK -> ".powerInput()" - data.material == Material.END_ROD -> ".endRod()" data.material == EXTRACTOR_TYPE -> ".extractor()" data.material == Material.HOPPER -> ".hopper()" data.material == Material.DISPENSER -> ".dispenser()" @@ -161,7 +160,7 @@ object StructureCreator : SLCommand() { data.material == Material.GRINDSTONE -> { data as Grindstone val facing = RelativeFace[forwards, data.facing] - ".dispenser(PrepackagedPreset.simpleDirectional(RelativeFace.$facing, example = Material.GRINDSTONE.createBlockData()))" + ".grindstone(PrepackagedPreset.simpleDirectional(RelativeFace.$facing, example = Material.GRINDSTONE.createBlockData()))" } data.material.isTrapdoor -> { @@ -170,6 +169,18 @@ object StructureCreator : SLCommand() { ".anyTrapdoor(PrepackagedPreset.trapdoor(Bisected.Half.${data.half}, RelativeFace.$facing, ${data.isPowered}, ${data.isOpen}))" } + data.material == Material.END_ROD -> { + data as Directional + val facing = RelativeFace[forwards, data.facing] + ".endRod(PrepackagedPreset.simpleDirectional(RelativeFace.$facing, example = Material.GRINDSTONE.createBlockData()))" + } + + data.material == Material.LIGHTNING_ROD -> { + data as Directional + val facing = RelativeFace[forwards, data.facing] + ".lightningRod(PrepackagedPreset.simpleDirectional(RelativeFace.$facing, example = Material.GRINDSTONE.createBlockData()))" + } + data.material == Material.SPONGE -> ".sponge()" data.material == Material.WET_SPONGE -> ".sponge()" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 32ce48ae00..d83cb23fae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -481,8 +481,8 @@ class MultiblockShape { fun extractor() = type(EXTRACTOR_TYPE) fun sponge() = anyType(Material.SPONGE, Material.WET_SPONGE, alias = "sponge") - fun endRod() = type(Material.END_ROD) - fun lightningRod() = type(Material.LIGHTNING_ROD) + fun endRod(edit: BlockRequirement.() -> Unit = {}) = type(Material.END_ROD, edit) + fun lightningRod(edit: BlockRequirement.() -> Unit = {}) = type(Material.LIGHTNING_ROD, edit) fun hopper() = type(Material.HOPPER) fun anyPipedInventory() = filteredTypes("any container block", edit = { setExample(Material.CHEST.createBlockData()) }) { Pipes.isPipedInventory(it) } From 8e5a8f3f6d8429ac987d39958ac7a741944f0411 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 10:57:11 -0600 Subject: [PATCH 340/500] add inventories --- .../horizonsend/ion/server/command/admin/StructureCreator.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index b15f1699b2..ec163e3d9c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.features.transport.old.Wires +import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.isConcrete @@ -192,6 +193,7 @@ object StructureCreator : SLCommand() { data.material == Material.MAGMA_BLOCK -> ".thrusterBlock()" data.material == Material.SEA_LANTERN -> ".thrusterBlock()" + Pipes.isPipedInventory(data.material) -> ".anyPipedInventory()" else -> ".type(Material.${data.material.name})" } From 90a2c6443961182488437c2c200749a68ef3484e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 13:59:09 -0600 Subject: [PATCH 341/500] untested solar panels --- .../transport/TransportConfiguration.kt | 10 ++- .../transport/manager/holders/CacheHolder.kt | 2 + .../manager/holders/ChunkCacheHolder.kt | 14 +-- .../manager/holders/ShipCacheHolder.kt | 12 +-- .../nodes/cache/PowerTransportCache.kt | 4 +- .../nodes/cache/solarpanel/SolarPanelCache.kt | 90 +++++++++++++++++++ .../features/transport/util/CacheType.kt | 9 ++ 7 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt index 0b81d93994..1c65157e5a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt @@ -4,12 +4,18 @@ import kotlinx.serialization.Serializable @Serializable data class TransportConfiguration( - val extractorConfiguration: ExtractorConfiguration = ExtractorConfiguration() + val extractorConfiguration: ExtractorConfiguration = ExtractorConfiguration(), + val powerConfiguration: PowerTransportConfiguration = PowerTransportConfiguration() ) { @Serializable data class ExtractorConfiguration( val extractorTickIntervalMS: Long = 2000, - val maxPowerRemovedPerExtractorTick: Int = 1000, val maxFluidRemovedPerExtractorTick: Int = 1000, ) + + @Serializable + data class PowerTransportConfiguration( + val maxPowerRemovedPerExtractorTick: Int = 1000, + val solarPanelTickPower: Int = 100 + ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt index 17d5079234..96bafff067 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node @@ -8,6 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World interface CacheHolder { + val transportManager: TransportManager val cache: T fun getWorld(): World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt index 65acbfe3db..a8a7ec224a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt @@ -12,27 +12,27 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import org.bukkit.World import kotlin.properties.Delegates -class ChunkCacheHolder private constructor (val manager: ChunkTransportManager) : CacheHolder { +class ChunkCacheHolder private constructor (override val transportManager: ChunkTransportManager) : CacheHolder { override var cache: T by Delegates.notNull(); private set constructor(manager: ChunkTransportManager, network: (ChunkCacheHolder) -> T) : this(manager) { this.cache = network(this) } - override fun getWorld(): World = manager.chunk.world + override fun getWorld(): World = transportManager.chunk.world override fun getOrCacheGlobalNode(key: BlockKey): Node? { val chunkX = getX(key).shr(4) val chunkZ = getZ(key).shr(4) - val isThisChunk = chunkX == manager.chunk.x && chunkZ == manager.chunk.z + val isThisChunk = chunkX == transportManager.chunk.x && chunkZ == transportManager.chunk.z if (isThisChunk) { return cache.getOrCache(key) } - val xDiff = manager.chunk.x - chunkX - val zDiff = manager.chunk.z - chunkZ + val xDiff = transportManager.chunk.x - chunkX + val zDiff = transportManager.chunk.z - chunkZ if (xDiff > 1 || xDiff < -1) return null if (zDiff > 1 || zDiff < -1) return null @@ -46,10 +46,10 @@ class ChunkCacheHolder private constructor (val manager: Chun } override fun getMultiblockManager(): MultiblockManager { - return manager.chunk.multiblockManager + return transportManager.chunk.multiblockManager } override fun getExtractorManager(): ExtractorManager { - return manager.extractorManager + return transportManager.extractorManager } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 9bd592deae..141c0613ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -11,18 +11,18 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World import kotlin.properties.Delegates -class ShipCacheHolder(val manager: ShipTransportManager) : CacheHolder { +class ShipCacheHolder(override val transportManager: ShipTransportManager) : CacheHolder { override var cache: T by Delegates.notNull(); private set constructor(manager: ShipTransportManager, network: (ShipCacheHolder) -> T) : this(manager) { this.cache = network(this) } - override fun getWorld(): World = manager.starship.world + override fun getWorld(): World = transportManager.starship.world override fun handleLoad() { - manager.starship.iterateBlocks { x, y, z -> - IonChunk[manager.starship.world, x, z]?.let { cache.type.get(it).invalidate(x, y, z) } + transportManager.starship.iterateBlocks { x, y, z -> + IonChunk[transportManager.starship.world, x, z]?.let { cache.type.get(it).invalidate(x, y, z) } cache.cache(toBlockKey(x, y, z)) } } @@ -37,10 +37,10 @@ class ShipCacheHolder(val manager: ShipTransportManager) : Ca } override fun getMultiblockManager(): MultiblockManager { - return manager.starship.multiblockManager + return transportManager.starship.multiblockManager } override fun getExtractorManager(): ExtractorManager { - return manager.extractorManager + return transportManager.extractorManager } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 1e4a3d3d9d..90907eccff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -52,7 +52,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC if (destinations.isEmpty()) return@submit - val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() + val transferLimit = (IonServer.transportSettings.powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() val transferred = minOf(source.powerStorage.getPower(), transferLimit) // Store this just in case @@ -77,7 +77,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC /** * Runs the power transfer from the source to the destinations. pending rewrite **/ - private fun runPowerTransfer(source: Node.NodePositionData, rawDestinations: List, availableTransferPower: Int): Int { + fun runPowerTransfer(source: Node.NodePositionData, rawDestinations: List, availableTransferPower: Int): Int { if (rawDestinations.isEmpty()) return availableTransferPower val filteredDestinations = rawDestinations.filter { destinationLoc -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt new file mode 100644 index 0000000000..6214a3c79c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt @@ -0,0 +1,90 @@ +package net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel + +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.NodeCacheFactory +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe +import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.Material.DAYLIGHT_DETECTOR +import org.bukkit.Material.DIAMOND_BLOCK +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.data.type.DaylightDetector +import kotlin.math.roundToInt + +class SolarPanelCache(holder: CacheHolder) : TransportCache(holder) { + override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(CRAFTING_TABLE, SolarPanelComponent.CraftingTable) + .addSimpleNode(DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) + .addSimpleNode(DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) + .build() + + override val type: CacheType = CacheType.SOLAR_PANELS + + sealed interface SolarPanelComponent: Node { + data object CraftingTable: SolarPanelComponent + data object DiamondBlock: SolarPanelComponent + data object DaylightDetector: SolarPanelComponent + + // Unneeded, just piggyback off of the node cache for speed + override val cacheType: CacheType get() = CacheType.POWER + override val pathfindingResistance: Double get() = 0.0 + override fun getTransferableDirections(backwards: BlockFace): Set = setOf() + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false + } + + fun isSolarPanel(extractorKey: BlockKey): Boolean { + if (getOrCache(extractorKey) !is SolarPanelComponent.CraftingTable) return false + if (getOrCache(getRelative(extractorKey, BlockFace.UP, 1)) !is SolarPanelComponent.DiamondBlock) return false + if (getOrCache(getRelative(extractorKey, BlockFace.UP, 2)) !is SolarPanelComponent.DaylightDetector) return false + return true + } + + override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { + if (!isSolarPanel(location)) return@submit + + val transportPower = getPower(holder.getWorld(), location, delta) + if (transportPower == 0) return@submit + + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(location) { node -> + holder.getWorld().ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + } + + if (destinations.isEmpty()) return@submit + + holder.transportManager.powerNodeManager.cache.runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + holder.getWorld(), + location, + BlockFace.SELF + ), + destinations, + transportPower + ) + }} + + fun getPower(world: World, detectorPosition: BlockKey, delta: Double): Int { + val powerMultiplier = if (world.environment == World.Environment.NORMAL) 1.0 else 0.5 + val data = getBlockDataSafe(world, getX(detectorPosition), getY(detectorPosition), getZ(detectorPosition)) as? DaylightDetector ?: return 0 + val powerRatio = data.power.toDouble() / data.maximumPower.toDouble() + + val base = IonServer.transportSettings.powerConfiguration.solarPanelTickPower * delta + return (base * powerRatio * powerMultiplier).roundToInt() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index b00a385a15..53dcd71f28 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -18,6 +18,15 @@ enum class CacheType(val namespacedKey: NamespacedKey) { return ship.transportManager.powerNodeManager.cache } }, + SOLAR_PANELS(NamespacedKeys.POWER_TRANSPORT) { + override fun get(chunk: IonChunk): PowerTransportCache { + return chunk.transportNetwork.powerNodeManager.cache + } + + override fun get(ship: ActiveStarship): PowerTransportCache { + return ship.transportManager.powerNodeManager.cache + } + }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { override fun get(chunk: IonChunk): FluidTransportCache { return chunk.transportNetwork.fluidNodeManager.cache From 9529e960a8da1990dd09abb6783c8955ea863bb7 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 14:30:44 -0600 Subject: [PATCH 342/500] Register solar panel cache, proper network type --- .../manager/ChunkTransportManager.kt | 10 +++ .../transport/manager/ShipTransportManager.kt | 3 + .../transport/manager/TransportManager.kt | 2 + .../nodes/cache/PowerTransportCache.kt | 78 ++++++++++++------- .../nodes/cache/solarpanel/SolarPanelCache.kt | 41 ++-------- .../features/transport/util/CacheType.kt | 10 +-- 6 files changed, 79 insertions(+), 65 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 5e9898174c..63fded0687 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.Extracto import net.horizonsend.ion.server.features.transport.manager.holders.ChunkCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -15,7 +16,9 @@ import org.bukkit.block.data.BlockData class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { override val extractorManager: ExtractorManager = ChunkExtractorManager(this) + override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } + override val solarPanelManager = ChunkCacheHolder(this) { SolarPanelCache(it) } override val fluidNodeManager = ChunkCacheHolder(this) { FluidTransportCache(it) } // val pipeGrid = PowerNodeManager(this) // TODO @@ -25,12 +28,14 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { fun setup() { powerNodeManager.handleLoad() + solarPanelManager.handleLoad() fluidNodeManager.handleLoad() NewTransport.registerTransportManager(this) } fun onUnload() { powerNodeManager.handleUnload() + solarPanelManager.handleUnload() fluidNodeManager.handleUnload() NewTransport.removeTransportManager(this) } @@ -41,29 +46,34 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { fun invalidateCache(key: BlockKey) { powerNodeManager.cache.invalidate(key) + solarPanelManager.cache.invalidate(key) fluidNodeManager.cache.invalidate(key) } fun processBlockRemoval(key: BlockKey) { powerNodeManager.cache.invalidate(key) + solarPanelManager.cache.invalidate(key) fluidNodeManager.cache.invalidate(key) // pipeGrid.processBlockRemoval(key) } fun processBlockChange(block: Block) { powerNodeManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) + solarPanelManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) fluidNodeManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) // pipeGrid.processBlockAddition(key, new) } fun processBlockChange(position: BlockKey, data: BlockData) { powerNodeManager.cache.invalidate(position) + solarPanelManager.cache.invalidate(position) fluidNodeManager.cache.invalidate(position) // pipeGrid.processBlockAddition(key, new) } fun refreshBlock(position: BlockKey) { powerNodeManager.cache.invalidate(position) + solarPanelManager.cache.invalidate(position) fluidNodeManager.cache.invalidate(position) // pipeGrid.processBlockAddition(key, new) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 191f96939d..3cccfb3f61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -4,9 +4,11 @@ import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.manager.holders.ShipCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.nodes.inputs.ShipInputManager @@ -15,6 +17,7 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { private val inputManager = ShipInputManager(this) override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } + override val solarPanelManager: CacheHolder = ShipCacheHolder(this) { SolarPanelCache(it) } override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } init { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 82d7d4231e..d6c6794e44 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -4,11 +4,13 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.Extracto import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager abstract class TransportManager { abstract val extractorManager: ExtractorManager abstract val powerNodeManager: CacheHolder + abstract val solarPanelManager: CacheHolder abstract val fluidNodeManager: CacheHolder abstract fun getInputProvider(): InputManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 90907eccff..07bdeae92f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -40,39 +40,65 @@ class PowerTransportCache(holder: CacheHolder) : TransportC .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() - override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { - val world = holder.getWorld() - val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } - val source = sources.randomOrNull() ?: return@submit //TODO take from all - - // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + override fun tickExtractor(location: BlockKey, delta: Double) { + val solarCache = holder.transportManager.solarPanelManager.cache + if (solarCache.isSolarPanel(location)) NewTransport.executor.submit { + val transportPower = solarCache.getPower(holder.getWorld(), location, delta) + if (transportPower == 0) return@submit + + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(location) { node -> + holder.getWorld().ion.inputManager.getHolders(CacheType.POWER, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + } + + if (destinations.isEmpty()) return@submit + + holder.transportManager.powerNodeManager.cache.runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + holder.getWorld(), + location, + BlockFace.SELF + ), + destinations, + transportPower + ) } - if (destinations.isEmpty()) return@submit + NewTransport.executor.submit { + val world = holder.getWorld() + val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } + val source = sources.randomOrNull() ?: return@submit //TODO take from all + + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(location) { node -> + world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + } - val transferLimit = (IonServer.transportSettings.powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() - val transferred = minOf(source.powerStorage.getPower(), transferLimit) + if (destinations.isEmpty()) return@submit - // Store this just in case - val missing = source.powerStorage.removePower(transferred) + val transferLimit = (IonServer.transportSettings.powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() + val transferred = minOf(source.powerStorage.getPower(), transferLimit) - val remainder = runPowerTransfer( - Node.NodePositionData( - PowerNode.PowerExtractorNode, - world, - location, - BlockFace.SELF - ), - destinations, - (transferred - missing) - ) + // Store this just in case + val missing = source.powerStorage.removePower(transferred) - if (remainder > 0) { - source.powerStorage.addPower(remainder) + val remainder = runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + world, + location, + BlockFace.SELF + ), + destinations, + (transferred - missing) + ) + + if (remainder > 0) { + source.powerStorage.addPower(remainder) + } } - }} + } /** * Runs the power transfer from the source to the destinations. pending rewrite diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt index 6214a3c79c..484f8eded3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt @@ -1,16 +1,12 @@ package net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.NodeCacheFactory import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node -import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode -import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -40,7 +36,7 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol data object DaylightDetector: SolarPanelComponent // Unneeded, just piggyback off of the node cache for speed - override val cacheType: CacheType get() = CacheType.POWER + override val cacheType: CacheType get() = CacheType.SOLAR_PANELS override val pathfindingResistance: Double get() = 0.0 override fun getTransferableDirections(backwards: BlockFace): Set = setOf() override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false @@ -48,37 +44,12 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol } fun isSolarPanel(extractorKey: BlockKey): Boolean { - if (getOrCache(extractorKey) !is SolarPanelComponent.CraftingTable) return false - if (getOrCache(getRelative(extractorKey, BlockFace.UP, 1)) !is SolarPanelComponent.DiamondBlock) return false - if (getOrCache(getRelative(extractorKey, BlockFace.UP, 2)) !is SolarPanelComponent.DaylightDetector) return false + if (getOrCacheNode(CacheType.SOLAR_PANELS, holder.getWorld(), extractorKey) !is SolarPanelComponent.CraftingTable) return false + if (getOrCacheNode(CacheType.SOLAR_PANELS, holder.getWorld(), getRelative(extractorKey, BlockFace.UP, 1)) !is SolarPanelComponent.DiamondBlock) return false + if (getOrCacheNode(CacheType.SOLAR_PANELS, holder.getWorld(), getRelative(extractorKey, BlockFace.UP, 2)) !is SolarPanelComponent.DaylightDetector) return false return true } - override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { - if (!isSolarPanel(location)) return@submit - - val transportPower = getPower(holder.getWorld(), location, delta) - if (transportPower == 0) return@submit - - // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - holder.getWorld().ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } - } - - if (destinations.isEmpty()) return@submit - - holder.transportManager.powerNodeManager.cache.runPowerTransfer( - Node.NodePositionData( - PowerNode.PowerExtractorNode, - holder.getWorld(), - location, - BlockFace.SELF - ), - destinations, - transportPower - ) - }} - fun getPower(world: World, detectorPosition: BlockKey, delta: Double): Int { val powerMultiplier = if (world.environment == World.Environment.NORMAL) 1.0 else 0.5 val data = getBlockDataSafe(world, getX(detectorPosition), getY(detectorPosition), getZ(detectorPosition)) as? DaylightDetector ?: return 0 @@ -87,4 +58,6 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol val base = IonServer.transportSettings.powerConfiguration.solarPanelTickPower * delta return (base * powerRatio * powerMultiplier).roundToInt() } + + override fun tickExtractor(location: BlockKey, delta: Double) { } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index 53dcd71f28..5de0718a41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.NamespacedKey @@ -19,12 +20,12 @@ enum class CacheType(val namespacedKey: NamespacedKey) { } }, SOLAR_PANELS(NamespacedKeys.POWER_TRANSPORT) { - override fun get(chunk: IonChunk): PowerTransportCache { - return chunk.transportNetwork.powerNodeManager.cache + override fun get(chunk: IonChunk): SolarPanelCache { + return chunk.transportNetwork.solarPanelManager.cache } - override fun get(ship: ActiveStarship): PowerTransportCache { - return ship.transportManager.powerNodeManager.cache + override fun get(ship: ActiveStarship): SolarPanelCache { + return ship.transportManager.solarPanelManager.cache } }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { @@ -37,7 +38,6 @@ enum class CacheType(val namespacedKey: NamespacedKey) { } }, - ; abstract fun get(chunk: IonChunk): TransportCache From 432ba08c4f7765a3c6dd250e2018cd52511c1f3d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 23:14:18 -0600 Subject: [PATCH 343/500] fix bug, organize --- .../nodes/cache/PowerTransportCache.kt | 95 ++++++++++--------- .../nodes/cache/solarpanel/SolarPanelCache.kt | 3 +- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 07bdeae92f..a8d3e6036e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter @@ -42,62 +43,66 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override fun tickExtractor(location: BlockKey, delta: Double) { val solarCache = holder.transportManager.solarPanelManager.cache - if (solarCache.isSolarPanel(location)) NewTransport.executor.submit { - val transportPower = solarCache.getPower(holder.getWorld(), location, delta) - if (transportPower == 0) return@submit + if (solarCache.isSolarPanel(location)) tickSolarPanel(location, delta, solarCache) - // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - holder.getWorld().ion.inputManager.getHolders(CacheType.POWER, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } - } + tickPowerExtractor(location, delta) + } - if (destinations.isEmpty()) return@submit - - holder.transportManager.powerNodeManager.cache.runPowerTransfer( - Node.NodePositionData( - PowerNode.PowerExtractorNode, - holder.getWorld(), - location, - BlockFace.SELF - ), - destinations, - transportPower - ) + private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.executor.submit { + val world = holder.getWorld() + val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } + val source = sources.randomOrNull() ?: return@submit //TODO take from all + + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(location) { node -> + world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } } - NewTransport.executor.submit { - val world = holder.getWorld() - val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } - val source = sources.randomOrNull() ?: return@submit //TODO take from all + if (destinations.isEmpty()) return@submit - // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } - } + val transferLimit = (IonServer.transportSettings.powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() + val transferred = minOf(source.powerStorage.getPower(), transferLimit) - if (destinations.isEmpty()) return@submit + // Store this just in case + val missing = source.powerStorage.removePower(transferred) - val transferLimit = (IonServer.transportSettings.powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() - val transferred = minOf(source.powerStorage.getPower(), transferLimit) + val remainder = runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + world, + location, + BlockFace.SELF + ), + destinations, + (transferred - missing) + ) - // Store this just in case - val missing = source.powerStorage.removePower(transferred) + if (remainder > 0) { + source.powerStorage.addPower(remainder) + } + } - val remainder = runPowerTransfer( - Node.NodePositionData( - PowerNode.PowerExtractorNode, - world, - location, - BlockFace.SELF - ), - destinations, - (transferred - missing) - ) + private fun tickSolarPanel(location: BlockKey, delta: Double, solarCache: SolarPanelCache) = NewTransport.executor.submit { + val transportPower = solarCache.getPower(holder.getWorld(), location, delta) + if (transportPower == 0) return@submit - if (remainder > 0) { - source.powerStorage.addPower(remainder) - } + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(location) { node -> + holder.getWorld().ion.inputManager.getHolders(CacheType.POWER, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } } + + if (destinations.isEmpty()) return@submit + + holder.transportManager.powerNodeManager.cache.runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + holder.getWorld(), + location, + BlockFace.SELF + ), + destinations, + transportPower + ) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt index 484f8eded3..7909b85bb7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt @@ -50,7 +50,8 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol return true } - fun getPower(world: World, detectorPosition: BlockKey, delta: Double): Int { + fun getPower(world: World, extractPos: BlockKey, delta: Double): Int { + val detectorPosition = getRelative(extractPos, BlockFace.UP, 2) val powerMultiplier = if (world.environment == World.Environment.NORMAL) 1.0 else 0.5 val data = getBlockDataSafe(world, getX(detectorPosition), getY(detectorPosition), getZ(detectorPosition)) as? DaylightDetector ?: return 0 val powerRatio = data.power.toDouble() / data.maximumPower.toDouble() From e6fdaa180815caeefe00049ff9231b1f841155e4 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 26 Nov 2024 23:39:41 -0600 Subject: [PATCH 344/500] prevent some wireless power transfer scenarios --- .../multiblock/entity/MultiblockEntity.kt | 4 +++- .../transport/nodes/cache/TransportCache.kt | 12 +++++++++++- .../utils/coordinates/Coordinates.kt | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 39435c0cc4..5682115a60 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -79,7 +79,7 @@ abstract class MultiblockEntity( **/ val vec3i get() = Vec3i(x, y, z) - val locationKey = toBlockKey(x, y, z) + val locationKey get() = toBlockKey(x, y, z) fun processRemoval() { removed = true @@ -153,6 +153,8 @@ abstract class MultiblockEntity( } fun getSignLocation() = getSignFromOrigin(world, vec3i, structureDirection).location + fun getSignBlock() = getSignFromOrigin(world, vec3i, structureDirection) + fun getSignKey() = getRelative(locationKey, structureDirection.oppositeFace) /** * Gets the origin block of this multiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 26b507b047..a612e6139c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isAdjacent import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block @@ -78,7 +79,16 @@ abstract class TransportCache(val holder: CacheHolder<*>) { val inputManager = holder.getWorld().ion.inputManager val registered = inputManager.getHolders(type, location) - val adjacentBlocks = stupidOffsets.mapNotNull { MultiblockEntities.getMultiblockEntity(holder.getWorld(), it.x, it.y, it.z) } + // The stupid offsets are a list of locations that a multiblock entity would be accessible from if its sign were touching the provided location + // Doing a call to try to find a sign is a lot more expensive since it has a getChunk call + // + // If this actually finds an entity, it makes sure that its sign block is adjacent to the input + val adjacentBlocks = stupidOffsets.mapNotNull { + MultiblockEntities.getMultiblockEntity(holder.getWorld(), it.x, it.y, it.z)?.takeIf { entity -> + val signLoc = entity.getSignKey() + isAdjacent(signLoc, location) + } + } return registered.plus(adjacentBlocks) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt index c4d734e6bb..86a2bfabc5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/coordinates/Coordinates.kt @@ -16,6 +16,7 @@ import org.joml.Vector3f import java.util.concurrent.ThreadLocalRandom import java.util.function.Consumer import kotlin.math.PI +import kotlin.math.abs import kotlin.math.acos import kotlin.math.atan import kotlin.math.atan2 @@ -537,3 +538,19 @@ fun Location.getLocationNear(minDistance: Double, maxDistance: Double): Location fun Vec3i.toChunkLocal(): Vec3i = Vec3i(x % 16, y, z % 16) fun Vec3i.getRelative(direction: BlockFace, distance: Int = 1) = plus(Vec3i(direction.modX * distance, direction.modY * distance, direction.modZ * distance)) + +fun isAdjacent(first: BlockKey, other: BlockKey): Boolean { + val xDiff = abs(getX(first) - getX(other)) + val yDiff = abs(getY(first) - getY(other)) + val zDiff = abs(getZ(first) - getZ(other)) + + return (xDiff + yDiff + zDiff) == 1 +} + +fun isAdjacent(first: Vec3i, other: Vec3i): Boolean { + val xDiff = abs(first.x - other.x) + val yDiff = abs(first.y - other.y) + val zDiff = abs(first.z - other.z) + + return (xDiff + yDiff + zDiff) == 1 +} From 9f49556d0ce5853971e493fc3f115494fc21e996 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 27 Nov 2024 13:22:44 -0600 Subject: [PATCH 345/500] big fixes, reliability, re-enable sign migrator --- .../features/multiblock/MultiblockRegistration.kt | 2 ++ .../features/multiblock/entity/MultiblockEntity.kt | 8 ++++++++ .../features/multiblock/entity/type/RecipeEntity.kt | 1 + .../fluid/collector/CanisterGasCollectorMultiblock.kt | 6 +++--- .../ion/server/features/world/chunk/IonChunk.kt | 10 ++++++++-- .../ion/server/features/world/data/DataFixers.kt | 5 ++--- .../server/features/world/data/SignFixerEntrance.kt | 2 +- 7 files changed, 25 insertions(+), 9 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 91e5cb9ba0..55475a37e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -279,7 +279,9 @@ object MultiblockRegistration : IonServerComponent() { // Gas registerMultiblock(PipedGasCollectorMultiblock) registerMultiblock(CanisterGasCollectorMultiblock, "GasCollectorMultiblock") + registerMultiblock(CanisterGasCollectorMultiblock) registerMultiblock(CanisterVentMultiblock, "VentMultiblock") + registerMultiblock(CanisterVentMultiblock) registerMultiblock(GasPowerPlantMultiblock) registerMultiblock(ElectrolysisMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 5682115a60..18405e30aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing +import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isBlockLoaded import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Location @@ -292,6 +293,13 @@ abstract class MultiblockEntity( return sign.block.getRelative(multiblockDirection) } + /** Get the multiblock's origin from its sign */ + fun getOriginFromSignIfLoaded(sign: Sign): Block? { + val multiblockDirection = sign.getFacing().oppositeFace + + return sign.block.getRelativeIfLoaded(multiblockDirection) + } + /** Get the sign position from a multiblock's orientation and origin */ fun getSignFromOrigin(origin: Block, structureDirection: BlockFace): Block = origin.getRelative(structureDirection.oppositeFace) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt index d87db401c9..9cecdad368 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt @@ -15,6 +15,7 @@ interface RecipeEntity : ProgressMultiblock, SyncTickingMultiblockEntity { } override fun tick() { + return executeRecipes() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt index 3890c1b772..841fe10023 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/collector/CanisterGasCollectorMultiblock.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.gas.type.Gas import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape @@ -67,11 +67,11 @@ object CanisterGasCollectorMultiblock : Multiblock(), EntityMultiblock dataVersion }) { + for (signFixer in signDataFixers.filter { it.dataVersion > dataVersion }.sortedBy { it.dataVersion }) { signFixer.fixSign(sign) sign.persistentDataContainer.set(DATA_VERSION, INTEGER, signFixer.dataVersion) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt index 58e8996f59..878ec3e879 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/data/SignFixerEntrance.kt @@ -28,7 +28,7 @@ object SignFixerEntrance { val block = chunk.inner.getBlock(x, y, z) val state = block.state as Sign - DataFixers.handleMultiblockSignLoad(state) + DataFixers.handleSignLoad(state) } } } From d1e4bb64657f14191e0618f497098c2ee77f6410 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 27 Nov 2024 13:24:27 -0600 Subject: [PATCH 346/500] don't disable the drill every tick --- .../server/features/multiblock/type/drills/DrillMultiblock.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index b6352cad09..235ca9d19a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -207,6 +207,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } fun disable() { + if (!userManager.currentlyUsed()) return val sign = getSign() ?: return userManager.clear() From 8a6f70ea8ff1c97f46d3b4c949153ef3fca34944 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 27 Nov 2024 13:48:38 -0600 Subject: [PATCH 347/500] do that better --- .../server/features/multiblock/type/drills/DrillMultiblock.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 235ca9d19a..81f2cac03b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -136,6 +136,8 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M override val displayHandler: TextDisplayHandler = standardPowerDisplay(this) override fun tick() { + if (!userManager.currentlyUsed()) return + // Logout condition val player = userManager.getUserPlayer() ?: return disable() if (CombatTimer.isPvpCombatTagged(player)) { @@ -207,7 +209,6 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M } fun disable() { - if (!userManager.currentlyUsed()) return val sign = getSign() ?: return userManager.clear() From 28b8a50edad8462c1193970036ebc48ded6afcbd Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 27 Nov 2024 23:25:22 -0600 Subject: [PATCH 348/500] copy paper thread dump code into a command --- .../command/misc/TransportDebugCommand.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index ed62ca77e4..f85dde25f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.command.misc import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand +import io.papermc.paper.util.StacktraceDeobfuscator import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks @@ -15,6 +16,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.command.CommandSender import org.bukkit.entity.Player +import org.slf4j.Logger +import java.lang.management.ManagementFactory +import java.lang.management.ThreadInfo import java.util.concurrent.Executors @CommandPermission("starlegacy.transportdebug") @@ -52,4 +56,37 @@ object TransportDebugCommand : SLCommand() { sender.highlightBlocks(inputs, 50L) } + + @Subcommand("force dump") + fun forceDump(sender: Player) { + log.error("Entire Thread Dump:") + val threads = ManagementFactory.getThreadMXBean().dumpAllThreads(true, true) + for (thread in threads) { + dumpThread(thread, log) + } + } + + private fun dumpThread(thread: ThreadInfo, log: Logger) { + log.error("------------------------------") + // + log.error("Current Thread: " + thread.threadName) + log.error( + ("\tPID: " + thread.threadId + + " | Suspended: " + thread.isSuspended + + " | Native: " + thread.isInNative + + " | State: " + thread.threadState) + ) + if (thread.lockedMonitors.size != 0) { + log.error("\tThread is waiting on monitor(s):") + for (monitor in thread.lockedMonitors) { + log.error("\t\tLocked on:" + monitor.lockedStackFrame) + } + } + log.error("\tStack:") + // + for (stack in StacktraceDeobfuscator.INSTANCE.deobfuscateStacktrace(thread.stackTrace)) // Paper + { + log.error("\t\t" + stack) + } + } } From 548483af99656d68f058efe90a30bfab701935c1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 29 Nov 2024 15:05:50 -0600 Subject: [PATCH 349/500] Lag improvements, cleanup --- .../server/command/admin/IonChunkCommand.kt | 2 - .../command/misc/TransportDebugCommand.kt | 11 -- .../manager/ChunkMultiblockManager.kt | 5 +- .../transport/TransportConfiguration.kt | 4 +- .../manager/ChunkTransportManager.kt | 4 +- .../transport/nodes/cache/NodeCacheFactory.kt | 1 + .../nodes/cache/PowerTransportCache.kt | 4 +- .../transport/nodes/cache/TransportCache.kt | 16 +-- .../ion/server/features/world/IonWorld.kt | 10 +- .../features/world/chunk/ChunkRegion.kt | 107 ------------------ .../server/features/world/chunk/IonChunk.kt | 16 ++- 11 files changed, 31 insertions(+), 149 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index 0b7623cbde..d97b0bb187 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -12,7 +12,6 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -116,7 +115,6 @@ object IonChunkCommand : SLCommand() { val ionChunk = sender.chunk.ion() sender.information("Chunk: $ionChunk") - sender.information("World has: ${ionChunk.world.ion.regionPositions.values.distinct().size} unique regions") } @Subcommand("get node key") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index f85dde25f2..fe3ce2af8a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -9,7 +9,6 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig -import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -19,7 +18,6 @@ import org.bukkit.entity.Player import org.slf4j.Logger import java.lang.management.ManagementFactory import java.lang.management.ThreadInfo -import java.util.concurrent.Executors @CommandPermission("starlegacy.transportdebug") @CommandAlias("transportdebug|transportbug") @@ -37,15 +35,6 @@ object TransportDebugCommand : SLCommand() { Extractors.BUSY_PIPE_EXTRACTORS.clear() } - @Suppress("Unused") - @Subcommand("clear wirequeue") - fun onClearQueue(sender: CommandSender) { - val wireQueue = Wires.thread - - wireQueue.shutdownNow() - Wires.thread = Executors.newSingleThreadExecutor(Wires.threadFactory) - } - @Subcommand("dump inputs") fun dumpInputs(sender: Player, type: CacheType) { val inputManager = sender.world.ion.inputManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 57ecd91996..e6cd7e0557 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORED_MULTIBLOCK_ENTITIES_OLD @@ -20,8 +21,8 @@ import org.slf4j.Logger class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManager(log) { override val world: World = chunk.world - override fun getInputManager(): InputManager = chunk.region.world.inputManager - override fun getLinkageManager(): MultiblockLinkageManager = chunk.region.world.multiblockManager.linkageManager + override fun getInputManager(): InputManager = chunk.world.ion.inputManager + override fun getLinkageManager(): MultiblockLinkageManager = chunk.world.ion.multiblockManager.linkageManager /** * Logic upon the chunk being saved diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt index 1c65157e5a..3f5dba20ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt @@ -16,6 +16,8 @@ data class TransportConfiguration( @Serializable data class PowerTransportConfiguration( val maxPowerRemovedPerExtractorTick: Int = 1000, - val solarPanelTickPower: Int = 100 + val solarPanelTickPower: Int = 100, + val maxExtractorDestinations: Int = 100, + val maxSolarDestinations: Int = 100, ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 63fded0687..c0f85f952d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportC import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -20,10 +21,9 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } override val solarPanelManager = ChunkCacheHolder(this) { SolarPanelCache(it) } override val fluidNodeManager = ChunkCacheHolder(this) { FluidTransportCache(it) } -// val pipeGrid = PowerNodeManager(this) // TODO override fun getInputProvider(): InputManager { - return chunk.region.world.inputManager + return chunk.world.ion.inputManager } fun setup() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 2dfee0d690..102efb7167 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -54,6 +54,7 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val blockDataClass: KClass, val constructor: (T, BlockKey) -> Node) { + @Synchronized fun construct(blockData: BlockData, key: BlockKey): Node { @Suppress("UNCHECKED_CAST") return constructor.invoke(blockData as T, key) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index a8d3e6036e..8ff9ff23dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -73,7 +73,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC location, BlockFace.SELF ), - destinations, + destinations.take(IonServer.transportSettings.powerConfiguration.maxExtractorDestinations), (transferred - missing) ) @@ -100,7 +100,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC location, BlockFace.SELF ), - destinations, + destinations.take(IonServer.transportSettings.powerConfiguration.maxSolarDestinations), transportPower ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index a612e6139c..556540a47f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity @@ -22,19 +21,22 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block import org.bukkit.block.BlockFace +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.locks.ReentrantLock abstract class TransportCache(val holder: CacheHolder<*>) { - private val cache: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() + private val cache: ConcurrentHashMap = ConcurrentHashMap() private val mutex = Any() + private val lock = ReentrantLock() abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory abstract fun tickExtractor(location: BlockKey, delta: Double) - fun isCached(at: BlockKey): Boolean = synchronized(mutex) { cache.containsKey(at) } + fun isCached(at: BlockKey): Boolean = cache.keys.contains(at) - fun getCached(at: BlockKey): Node? = synchronized(mutex) { + fun getCached(at: BlockKey): Node? { val state = cache[at] ?: return null return when (state) { is CacheState.Empty -> null @@ -53,7 +55,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { cache(location, block) } - fun cache(location: BlockKey, block: Block): Node? = synchronized(mutex) { + fun cache(location: BlockKey, block: Block): Node? { val type = nodeFactory.cache(block) val state = if (type == null) CacheState.Empty else CacheState.Present(type) @@ -61,11 +63,11 @@ abstract class TransportCache(val holder: CacheHolder<*>) { return type } - fun invalidate(x: Int, y: Int, z: Int) = synchronized(mutex) { + fun invalidate(x: Int, y: Int, z: Int) { invalidate(toBlockKey(x, y, z)) } - fun invalidate(key: BlockKey) = synchronized(mutex) { + fun invalidate(key: BlockKey) { (cache.remove(key) as? CacheState.Present)?.node?.onInvalidate() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index ea46fc8b98..9a1829a9c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -1,15 +1,14 @@ package net.horizonsend.ion.server.features.world import com.destroystokyo.paper.event.server.ServerTickStartEvent +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.common.utils.configuration.Configuration import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.manager.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.inputs.WorldInputManager -import net.horizonsend.ion.server.features.world.chunk.ChunkRegion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.configuration.DefaultWorldConfiguration import net.horizonsend.ion.server.features.world.data.DataFixers @@ -28,7 +27,6 @@ import org.bukkit.event.world.WorldSaveEvent import org.bukkit.event.world.WorldUnloadEvent import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG_ARRAY -import java.util.concurrent.ConcurrentHashMap import kotlin.DeprecationLevel.ERROR class IonWorld private constructor( @@ -46,9 +44,7 @@ class IonWorld private constructor( * * Value: The IonChunk at that location **/ - private val chunks: ConcurrentHashMap = ConcurrentHashMap() - val regionPositions: ConcurrentHashMap = ConcurrentHashMap() - val chunkRegions: MutableSet = ObjectOpenHashSet() + private val chunks: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() val multiblockManager = WorldMultiblockManager(this) val inputManager = WorldInputManager(this) @@ -69,6 +65,8 @@ class IonWorld private constructor( return chunks[key] } + fun isChunkLoaded(key: Long) = chunks.keys.contains(key) + /** * Adds the chunk **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt deleted file mode 100644 index 3ac091e63a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/ChunkRegion.kt +++ /dev/null @@ -1,107 +0,0 @@ -package net.horizonsend.ion.server.features.world.chunk - -import net.horizonsend.ion.server.features.world.IonWorld -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES -import org.bukkit.Chunk -import java.util.concurrent.ConcurrentHashMap - -class ChunkRegion(val world: IonWorld) { - val chunks = ConcurrentHashMap() - - val size get() = chunks.values.size - - fun removeChunk(chunk: IonChunk) { - chunks.remove(chunk.locationKey) - } - - fun delete() { - chunks.forEach { - world.regionPositions.remove(it.value.locationKey) - } - world.chunkRegions.remove(this) - } - - companion object { - const val MAX_SIZE: Int = 50 - - fun loadChunk(chunk: Chunk) { - if (chunk.world.ion.getChunk(chunk.chunkKey) != null) { - return - } - - val region: ChunkRegion = findRegion(chunk) - val ionChunk = IonChunk.registerChunk(chunk, region) - - val key = chunk.chunkKey - - region.chunks[key] = ionChunk - chunk.world.ion.regionPositions[key] = region - - region.world.chunkRegions.add(region) - } - - fun unloadChunk(chunk: IonChunk) { - val region = chunk.region - - region.removeChunk(chunk) - - if (region.chunks.isEmpty()) region.delete() - } - - /** - * Will find a region for this chunk to join. - * - * If this chunk borders a region, and it can add another safely, join it. - * - * If there are two disconnected regions joined by this chunk, and they total less than the limit, combine them. - * - * If there is no region available, start a new one. - * - * Returns the region - **/ - fun findRegion(chunk: Chunk): ChunkRegion { - val neighbors = getNeighborRegions(chunk) - - val region: ChunkRegion = when (neighbors.size) { - 0 -> startNewRegion(chunk) - 1 -> { - val region = neighbors.first() - if (region.size > MAX_SIZE) startNewRegion(chunk) else region - } - in 2..4 -> { - neighbors.firstOrNull { it.size < MAX_SIZE } ?: startNewRegion(chunk) - } - else -> throw IllegalArgumentException() - } - - return region - } - - private fun getNeighborRegions(chunk: Chunk): Collection { - val chunkX = chunk.x - val chunkZ = chunk.z - - return CARDINAL_BLOCK_FACES.mapNotNull { direction -> - val newX = direction.modX + chunkX - val newZ = direction.modZ + chunkZ - - val key = Chunk.getChunkKey(newX, newZ) - chunk.world.ion.regionPositions[key] - } - } - - fun startNewRegion(chunk: Chunk): ChunkRegion { - val world = chunk.world.ion - val region = ChunkRegion(world) - world.chunkRegions.add(region) - - return region - } - } - - override fun toString(): String { - return "IonChunkRegion[${size} positions]" - } -} - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 6ba14b414e..c242db750a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -21,10 +21,7 @@ import org.bukkit.persistence.PersistentDataType.INTEGER import java.util.concurrent.ConcurrentHashMap import java.util.function.Consumer -class IonChunk( - val inner: Chunk, - val region: ChunkRegion, -) { +class IonChunk(val inner: Chunk) { var dataVersion = inner.persistentDataContainer.getOrDefault(NamespacedKeys.DATA_VERSION, INTEGER, 0) set (value) { world.persistentDataContainer.set(NamespacedKeys.DATA_VERSION, INTEGER, value) @@ -113,7 +110,10 @@ class IonChunk( loadingTasks.add(key) try { - ChunkRegion.loadChunk(event.chunk) + val chunk = event.chunk + if (chunk.world.ion.isChunkLoaded(key)) return + + val ionChunk = registerChunk(chunk) } catch (e: Throwable) { log.info("Problem when loading IonChunk ${event.chunk.x} ${event.chunk.z} in ${event.chunk.world.name}: ") e.printStackTrace() @@ -132,11 +132,10 @@ class IonChunk( * * It is imperative that every exception generated be handled **/ - fun registerChunk(chunk: Chunk, region: ChunkRegion): IonChunk { + fun registerChunk(chunk: Chunk): IonChunk { val ionWorld = chunk.world.ion - val ionChunk = IonChunk(chunk, region) - region.chunks[chunk.chunkKey] = ionChunk + val ionChunk = IonChunk(chunk) ionWorld.addChunk(ionChunk) @@ -157,7 +156,6 @@ class IonChunk( val removed = ionWorld.removeChunk(chunk) ?: return log.warn("Removed unregistered IonChunk!") removed.onUnload() - ChunkRegion.unloadChunk(removed) } /** From 3d9ec7d6925568134be4abb3862214eef26093ef Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 29 Nov 2024 15:25:57 -0600 Subject: [PATCH 350/500] check structure async then sync tick --- .../ion/server/features/multiblock/MultiblockTicking.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt index bbe2d28add..baf80560cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt @@ -27,13 +27,19 @@ object MultiblockTicking : IonServerComponent() { private fun tickSyncMultiblocks() = iterateManagers { manager -> for ((key, syncTicking) in manager.syncTickingMultiblockEntities) runCatching { - if (SyncTickingMultiblockEntity.preTick(syncTicking as MultiblockEntity)) syncTicking.tick() + checkStructureAsyncThenTick(syncTicking) }.onFailure { e -> log.warn("Exception ticking multiblock ${syncTicking.javaClass.simpleName} at ${toVec3i(key)}: ${e.message}") e.printStackTrace() } } + private fun checkStructureAsyncThenTick(entity: SyncTickingMultiblockEntity) = Tasks.async { + if (SyncTickingMultiblockEntity.preTick(entity as MultiblockEntity)) Tasks.sync { + entity.tick() + } + } + private fun tickAsyncMultiblocks() = iterateManagers { manager -> for ((key, asyncTicking) in manager.asyncTickingMultiblockEntities) runCatching { if (SyncTickingMultiblockEntity.preTick(asyncTicking as MultiblockEntity)) asyncTicking.tickAsync() From cd4f9746c156ac16e786d6a7780e04699d415c12 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 29 Nov 2024 15:42:08 -0600 Subject: [PATCH 351/500] misc --- .../server/features/transport/nodes/cache/TransportCache.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 556540a47f..0c62c3e106 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -22,19 +22,16 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.block.Block import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.locks.ReentrantLock abstract class TransportCache(val holder: CacheHolder<*>) { private val cache: ConcurrentHashMap = ConcurrentHashMap() - private val mutex = Any() - private val lock = ReentrantLock() abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory abstract fun tickExtractor(location: BlockKey, delta: Double) - fun isCached(at: BlockKey): Boolean = cache.keys.contains(at) + fun isCached(at: BlockKey): Boolean = cache.containsKey(at) fun getCached(at: BlockKey): Node? { val state = cache[at] ?: return null From 4a69064fd9a4defb96b9e4144000551f26cb5066 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 29 Nov 2024 16:45:06 -0600 Subject: [PATCH 352/500] fix auto crafter lag --- .../type/autocrafter/AutoCrafterMultiblock.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 9de2b9c532..bfd9c329aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -153,6 +153,8 @@ abstract class AutoCrafterMultiblock( private fun getRecipeHolder(): Inventory? = getInventory(0, 0, 1) private fun getOutput(): Inventory? = getInventory(+2, 0, 1) + private var resultHash: Int? = null + override fun tick() { val inputInventory: Inventory = getInput() ?: return sleepWithStatus(text("Not Intact", RED), 500) val recipeHolder: Inventory = getRecipeHolder() ?: return sleepWithStatus(text("Not Intact", RED), 500) @@ -246,8 +248,15 @@ abstract class AutoCrafterMultiblock( if (basePower != power) { powerStorage.setPower(power) } else { - // Nothing crafted, could be temporary resource shortage, pause for shorter time period - sleepWithStatus(result.displayName(), 200) + val newHash = result.hashCode() + if (resultHash != newHash) { + // Skip re-computing the display name, small but adds up with big factories + resultHash = newHash + // Nothing crafted, could be temporary resource shortage, pause for shorter time period + sleepWithStatus(result.displayName(), 200) + } else { + tickingManager.sleep(200) + } } } } From 0994351598a2d54b950c9449bd4d3bfe4ba967e8 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 29 Nov 2024 18:08:54 -0600 Subject: [PATCH 353/500] actually bother to load extractors, routine saving --- .../server/features/transport/NewTransport.kt | 12 ++++++++++++ .../transport/manager/ChunkTransportManager.kt | 7 +++++-- .../manager/extractors/ChunkExtractorManager.kt | 17 ++++++++++------- .../ion/server/features/world/IonWorld.kt | 2 ++ 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 241640ed7e..c05e6b6561 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -7,9 +7,11 @@ import net.horizonsend.ion.server.features.starship.event.build.StarshipPlaceBlo import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.World import org.bukkit.event.EventHandler @@ -43,6 +45,8 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } } } + + Tasks.asyncRepeat(120L, 120L, ::saveExtractors) } override fun onDisable() { @@ -135,4 +139,12 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } } } + + fun saveExtractors() { + for (world in Bukkit.getWorlds().map { it.ion }) { + val chunks = world.getAllChunks().values.forEach { chunk -> + chunk.transportNetwork.extractorManager.takeIf { it.needsSave }?.save() + } + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index c0f85f952d..e81c234f7f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ChunkCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache @@ -16,7 +15,7 @@ import org.bukkit.block.Block import org.bukkit.block.data.BlockData class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { - override val extractorManager: ExtractorManager = ChunkExtractorManager(this) + override val extractorManager: ChunkExtractorManager = ChunkExtractorManager(this) override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } override val solarPanelManager = ChunkCacheHolder(this) { SolarPanelCache(it) } @@ -26,6 +25,10 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { return chunk.world.ion.inputManager } + init { + extractorManager.onLoad() + } + fun setup() { powerNodeManager.handleLoad() solarPanelManager.handleLoad() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 1e6b823a22..a5096207c1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -9,7 +9,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import org.bukkit.persistence.PersistentDataType class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManager() { - var extractors = Long2ObjectOpenHashMap() + val extractors = Long2ObjectOpenHashMap() + + var needsSave: Boolean = false private val mutex = Any() @@ -22,14 +24,17 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag if (!manager.chunk.isInBounds(x, y, z)) return false val key = toBlockKey(x, y, z) extractors[key] = ExtractorData(key) + needsSave = true return true } override fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? = synchronized(mutex) { + needsSave = true return extractors.remove(toBlockKey(x, y, z)) } override fun removeExtractor(key: BlockKey): ExtractorData? = synchronized(mutex) { + needsSave = true return extractors.remove(key) } @@ -37,14 +42,12 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return extractors.contains(key) } - private val pdc get() = manager.chunk.inner.persistentDataContainer - - override fun onLoad() = synchronized(mutex) { - val existing = pdc.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) ?: return - extractors = existing.associateWithTo(Long2ObjectOpenHashMap()) { ExtractorData(it) } + override fun onLoad(): Unit = synchronized(mutex) { + val existing = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) ?: return + existing.associateWithTo(extractors) { ExtractorData(it) } } override fun save() { - pdc.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.keys.toLongArray()) + manager.chunk.inner.persistentDataContainer.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.keys.toLongArray()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index 9a1829a9c7..d5fb4685ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -233,4 +233,6 @@ class IonWorld private constructor( fun saveForbiddenBlocks() { world.persistentDataContainer.set(FORBIDDEN_BLOCKS, LONG_ARRAY, detectionForbiddenBlocks.toLongArray()) } + + fun getAllChunks() = chunks } From e8c32dd8eecc456b55a1af0f313fa596619fe0c1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 30 Nov 2024 13:55:38 -0600 Subject: [PATCH 354/500] Start work on filter implementation --- .../custom/items/misc/TransportFilterItem.kt | 28 +++++++++++ .../transport/filters/FilterAccess.kt | 44 +++++++++++++++++ .../transport/filters/FilterBlocks.kt | 49 +++++++++++++++++++ .../features/transport/filters/FilterData.kt | 27 ++++++++++ .../miscellaneous/registrations/Components.kt | 4 ++ .../persistence/NamespacedKeys.kt | 2 + 6 files changed, 154 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt new file mode 100644 index 0000000000..62b844c64c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt @@ -0,0 +1,28 @@ +package net.horizonsend.ion.server.features.custom.items.misc + +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.transport.filters.FilterBlock +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FILTER_DATA +import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.kyori.adventure.text.Component +import org.bukkit.Material +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.BlockStateMeta +import org.bukkit.persistence.PersistentDataType.STRING +import java.util.UUID +import java.util.function.Supplier + +class TransportFilterItem(identifier: String, val displayName: Component, private val filterBlock: Supplier) : CustomItem(identifier) { + override fun constructItemStack(): ItemStack { + return ItemStack(Material.BARREL).updateMeta { meta -> + meta as BlockStateMeta + meta.blockState = filterBlock.get().createState() + + meta.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) + meta.persistentDataContainer.set(FILTER_DATA, FilterData, FilterData(UUID.randomUUID())) + meta.displayName(displayName) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt new file mode 100644 index 0000000000..e9ebb4793a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt @@ -0,0 +1,44 @@ +package net.horizonsend.ion.server.features.transport.filters + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.custom.items.misc.Wrench +import net.horizonsend.ion.server.features.transport.filters.FilterBlock.Companion.FILTER_MATERIAL +import net.horizonsend.ion.server.features.transport.filters.FilterBlock.Companion.FILTER_STATE_TYPE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.block.Barrel +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.player.PlayerInteractEvent + +object FilterAccess : IonServerComponent() { + @EventHandler(priority = EventPriority.NORMAL) + fun onPlayerInteract(event: PlayerInteractEvent) { + val interactedWith = event.item ?: return + if (interactedWith.customItem !is Wrench) return + + val clicked = event.clickedBlock ?: return + val state = clicked.state + + if (!FILTER_STATE_TYPE.isInstance(state)) return + state as Barrel + + val type = FilterBlocks.getFilterBlock(state) ?: return + val filterData = state.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return + + type.openGUI(event.player, filterData) + } + + @EventHandler + fun onBlockBreak(event: BlockBreakEvent) { + if (event.block.type != FILTER_MATERIAL) return + + val state = event.block.state + if (state !is Barrel) return + + val filterType = FilterBlocks.getFilterBlock(state) ?: return + event.isDropItems = false + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt new file mode 100644 index 0000000000..1e8d106562 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt @@ -0,0 +1,49 @@ +package net.horizonsend.ion.server.features.transport.filters + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import org.bukkit.Material +import org.bukkit.block.Barrel +import org.bukkit.entity.Player +import org.bukkit.persistence.PersistentDataType.STRING +import java.util.function.Supplier + +object FilterBlocks : IonServerComponent() { + private val filters = mutableMapOf() + fun all(): Map = filters + + fun getFilterBlock(state: Barrel): FilterBlock? { + val identifier = state.persistentDataContainer.get(CUSTOM_ITEM, STRING) ?: return null + return filters[identifier] + } + + val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItems.FLUID_FILTER } + + private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { + val data = FilterBlock(identifier, cacheType, customItemSupplier) + filters[identifier] = data + return data + } +} + +class FilterBlock(val identifier: String, val cacheType: CacheType, private val customItemSupplier: Supplier) { + val customItem get() = customItemSupplier.get() + + fun createState(): Barrel { + val baseState = FILTER_MATERIAL.createBlockData().createBlockState() as Barrel + baseState.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) + return baseState + } + + fun openGUI(player: Player, data: FilterData) { + println("$player $data") + } + + companion object { + val FILTER_MATERIAL = Material.BARREL + val FILTER_STATE_TYPE = Barrel::class + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt new file mode 100644 index 0000000000..ff4f6367ea --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -0,0 +1,27 @@ +package net.horizonsend.ion.server.features.transport.filters + +import com.manya.pdc.base.UuidDataType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import java.util.UUID + +class FilterData( + val uuid: UUID, +) { + companion object : PersistentDataType { + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + override fun getComplexType(): Class = FilterData::class.java + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData { + return FilterData(primitive.get(NamespacedKeys.USER, UuidDataType())!!) + } + + override fun toPrimitive(complex: FilterData, context: PersistentDataAdapterContext): PersistentDataContainer { + val data = context.newPersistentDataContainer() + data.set(NamespacedKeys.USER,UuidDataType(), complex.uuid) + return data + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 229aa007df..c1020867ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -91,6 +91,8 @@ import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeacons import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCooldown import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.filters.FilterAccess +import net.horizonsend.ion.server.features.transport.filters.FilterBlocks import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig @@ -147,6 +149,8 @@ val components: List = listOf( PowerMachines, AreaShields, + FilterBlocks, + FilterAccess, TransportConfig.Companion, Extractors, Pipes, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index f1e5adf56c..e2aa4722a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -84,6 +84,8 @@ object NamespacedKeys { val POWER = key("power") val GAS = key("Gas") + val FILTER_DATA = key("filter_data") + val POWER_TRANSPORT = key("power_transport") val FLUID_TRANSPORT = key("gas_transport") val ITEM_TRANSPORT = key("item_transport") From 579d5e3146d0ea9bd52abbfad61f1036c7166c35 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 11:19:10 -0600 Subject: [PATCH 355/500] Allow placement, drops when shift right click --- .../custom/items/misc/TransportFilterItem.kt | 18 +++++++++++-- .../transport/filters/FilterAccess.kt | 25 +++++++++++-------- .../transport/filters/FilterBlocks.kt | 8 +++--- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt index 62b844c64c..83f322c5a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt @@ -8,10 +8,12 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component import org.bukkit.Material +import org.bukkit.block.Barrel +import org.bukkit.entity.LivingEntity +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.BlockStateMeta import org.bukkit.persistence.PersistentDataType.STRING -import java.util.UUID import java.util.function.Supplier class TransportFilterItem(identifier: String, val displayName: Component, private val filterBlock: Supplier) : CustomItem(identifier) { @@ -21,8 +23,20 @@ class TransportFilterItem(identifier: String, val displayName: Component, privat meta.blockState = filterBlock.get().createState() meta.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) - meta.persistentDataContainer.set(FILTER_DATA, FilterData, FilterData(UUID.randomUUID())) meta.displayName(displayName) } } + + fun createFor(state: Barrel): ItemStack { + return constructItemStack().updateMeta { meta -> + meta.persistentDataContainer.set(FILTER_DATA, FilterData, state.persistentDataContainer.get(FILTER_DATA, FilterData) ?: return@updateMeta) + } + } + + override val cancelSecondaryInteract: Boolean = false + + override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + if (event == null) return + event.isCancelled = false + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt index e9ebb4793a..32fdebf52c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt @@ -3,13 +3,13 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem import net.horizonsend.ion.server.features.custom.items.misc.Wrench -import net.horizonsend.ion.server.features.transport.filters.FilterBlock.Companion.FILTER_MATERIAL import net.horizonsend.ion.server.features.transport.filters.FilterBlock.Companion.FILTER_STATE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.Material import org.bukkit.block.Barrel +import org.bukkit.block.Block import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority -import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.player.PlayerInteractEvent object FilterAccess : IonServerComponent() { @@ -25,20 +25,23 @@ object FilterAccess : IonServerComponent() { state as Barrel val type = FilterBlocks.getFilterBlock(state) ?: return - val filterData = state.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return + + if (event.player.isSneaking) { + tryDrop(clicked, state, type) + return + } + + val filterData = state.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) type.openGUI(event.player, filterData) } - @EventHandler - fun onBlockBreak(event: BlockBreakEvent) { - if (event.block.type != FILTER_MATERIAL) return - - val state = event.block.state - if (state !is Barrel) return + fun tryDrop(block: Block, state: Barrel, type: FilterBlock) { + val dropLocation = block.location.toCenterLocation() + val item = type.customItem.createFor(state) - val filterType = FilterBlocks.getFilterBlock(state) ?: return - event.isDropItems = false + block.type = Material.AIR + block.world.dropItemNaturally(dropLocation, item) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt index 1e8d106562..01a9c6ca08 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.custom.items.misc.TransportFilterItem import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import org.bukkit.Material @@ -22,14 +22,14 @@ object FilterBlocks : IonServerComponent() { val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItems.FLUID_FILTER } - private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { + private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { val data = FilterBlock(identifier, cacheType, customItemSupplier) filters[identifier] = data return data } } -class FilterBlock(val identifier: String, val cacheType: CacheType, private val customItemSupplier: Supplier) { +class FilterBlock(val identifier: String, val cacheType: CacheType, private val customItemSupplier: Supplier) { val customItem get() = customItemSupplier.get() fun createState(): Barrel { @@ -38,7 +38,7 @@ class FilterBlock(val identifier: String, val cacheType: CacheType, private val return baseState } - fun openGUI(player: Player, data: FilterData) { + fun openGUI(player: Player, data: FilterData?) { println("$player $data") } From 44507893f01aeb170b194738c7b08acea1d00c18 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 11:49:10 -0600 Subject: [PATCH 356/500] load extractors if no data is present --- .../extractors/ChunkExtractorManager.kt | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index a5096207c1..3e01fe443f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe @@ -19,11 +21,18 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return extractors.values } - override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean = synchronized(mutex) { + override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != EXTRACTOR_TYPE) return false - if (!manager.chunk.isInBounds(x, y, z)) return false + if (!manager.chunk.isInBounds(x, y, z)) { + IonServer.slF4JLogger.warn("Extractor manager of ${manager.chunk} tried to register an extractor outside its bounds!") + return false + } val key = toBlockKey(x, y, z) - extractors[key] = ExtractorData(key) + + synchronized(mutex) { + extractors[key] = ExtractorData(key) + } + needsSave = true return true } @@ -42,12 +51,33 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return extractors.contains(key) } - override fun onLoad(): Unit = synchronized(mutex) { - val existing = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) ?: return - existing.associateWithTo(extractors) { ExtractorData(it) } + override fun onLoad() { + val existing = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) + + if (existing == null) { + loadFromChunk() + return + } + + synchronized(mutex) { existing.associateWithTo(extractors) { ExtractorData(it) } } } override fun save() { manager.chunk.inner.persistentDataContainer.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.keys.toLongArray()) } + + private fun loadFromChunk() = Tasks.async { + val snapshot = manager.chunk.inner.chunkSnapshot + val minBlockX = snapshot.x.shl(4) + val minBlockZ = snapshot.z.shl(4) + + for (x in 0..15) for (z in 0..15) for (y in manager.chunk.world.minHeight..snapshot.getHighestBlockYAt(x, z)) { + if (snapshot.getBlockType(x, y, z) != EXTRACTOR_TYPE) continue + val key = toBlockKey(x + minBlockX, y, z + minBlockZ) + extractors[key] = ExtractorData(key) + } + + + save() + } } From cc87a36e1c2731038af3e8a80a0666488d5af561 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 11:56:22 -0600 Subject: [PATCH 357/500] black fluid filter interactions if not holding a wrench --- .../server/features/transport/filters/FilterAccess.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt index 32fdebf52c..e12cecc65d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt @@ -15,9 +15,6 @@ import org.bukkit.event.player.PlayerInteractEvent object FilterAccess : IonServerComponent() { @EventHandler(priority = EventPriority.NORMAL) fun onPlayerInteract(event: PlayerInteractEvent) { - val interactedWith = event.item ?: return - if (interactedWith.customItem !is Wrench) return - val clicked = event.clickedBlock ?: return val state = clicked.state @@ -26,6 +23,12 @@ object FilterAccess : IonServerComponent() { val type = FilterBlocks.getFilterBlock(state) ?: return + val interactedWith = event.item ?: return + if (interactedWith.customItem !is Wrench) { + event.isCancelled = true + return + } + if (event.player.isSneaking) { tryDrop(clicked, state, type) return From 528259988d6d9a1e93ca472536b05071f4318d2d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 12:19:28 -0600 Subject: [PATCH 358/500] private --- .../ion/server/features/transport/filters/FilterAccess.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt index e12cecc65d..16c40e9b95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt @@ -39,7 +39,7 @@ object FilterAccess : IonServerComponent() { type.openGUI(event.player, filterData) } - fun tryDrop(block: Block, state: Barrel, type: FilterBlock) { + private fun tryDrop(block: Block, state: Barrel, type: FilterBlock) { val dropLocation = block.location.toCenterLocation() val item = type.customItem.createFor(state) From 4681d4ffa49fdb1dba7149aa05f3be86de071bca Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 12:50:38 -0600 Subject: [PATCH 359/500] Add serializable filter data --- .../transport/filters/FilterBlocks.kt | 2 +- .../features/transport/filters/FilterData.kt | 29 +++++++++++------ .../features/transport/filters/FilterKey.kt | 30 +++++++++++++++++ .../features/transport/filters/FilterType.kt | 32 +++++++++++++++++++ .../fluids/FluidPersistentDataType.kt | 17 ++++++++++ .../persistence/NamespacedKeys.kt | 3 ++ 6 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt index 01a9c6ca08..557ebf2faf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt @@ -38,7 +38,7 @@ class FilterBlock(val identifier: String, val cacheType: CacheType, private val return baseState } - fun openGUI(player: Player, data: FilterData?) { + fun openGUI(player: Player, data: FilterData<*>?) { println("$player $data") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt index ff4f6367ea..6e88f60ba9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -1,26 +1,35 @@ package net.horizonsend.ion.server.features.transport.filters -import com.manya.pdc.base.UuidDataType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -import java.util.UUID -class FilterData( - val uuid: UUID, +class FilterData( + val isWhitelist: Boolean, + val entries: MutableList> ) { - companion object : PersistentDataType { + companion object : PersistentDataType> { override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - override fun getComplexType(): Class = FilterData::class.java + override fun getComplexType(): Class> = FilterData::class.java - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData { - return FilterData(primitive.get(NamespacedKeys.USER, UuidDataType())!!) + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*> { + val whitelist = primitive.getOrDefault(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, true) + val entries = primitive.getOrDefault(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()) + val formatted = entries.mapTo(mutableListOf()) { entry -> + FilterKey.fromPrimitive(entry, context) + } + + return FilterData(whitelist, formatted) } - override fun toPrimitive(complex: FilterData, context: PersistentDataAdapterContext): PersistentDataContainer { + override fun toPrimitive(complex: FilterData<*>, context: PersistentDataAdapterContext): PersistentDataContainer { val data = context.newPersistentDataContainer() - data.set(NamespacedKeys.USER,UuidDataType(), complex.uuid) + + data.set(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, complex.isWhitelist) + val array = Array(complex.entries.size) { FilterKey.toPrimitive(complex.entries[it], context) } + data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, array) + return data } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt new file mode 100644 index 0000000000..f8639b1217 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.transport.filters + +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +class FilterKey(val entry: T, val type: FilterType) { + companion object : PersistentDataType> { + override fun getComplexType(): Class> = FilterKey::class.java + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterKey<*> { + val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! + val filterType = FilterType.filterTypes[filterTypeIdentifier]!! + + return FilterKey(filterType.retrieve(primitive)!!, filterType) + } + + override fun toPrimitive(complex: FilterKey<*>, context: PersistentDataAdapterContext): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + val typeIdentifier = complex.type.javaClass.simpleName + + pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) + complex.type.store(pdc, complex.entry) + + return pdc + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt new file mode 100644 index 0000000000..5a72d8d5ae --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -0,0 +1,32 @@ +package net.horizonsend.ion.server.features.transport.filters + +import com.manya.pdc.minecraft.ItemStackDataType +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +abstract class FilterType(val cacheType: CacheType, val typeClass: Class, val persistentDataType: PersistentDataType<*, T>) { + data object FluidType : FilterType(CacheType.FLUID, Fluid::class.java, FluidPersistentDataType) + data object ItemType : FilterType(CacheType.SOLAR_PANELS /*TODO*/, ItemStack::class.java, ItemStackDataType()) + + fun store(pdc: PersistentDataContainer, data: Any) { + if (!typeClass.isInstance(data)) return + @Suppress("UNCHECKED_CAST") + pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, data as T) + } + + fun retrieve(pdc: PersistentDataContainer): T? { + return pdc.get(NamespacedKeys.FILTER_ENTRY, persistentDataType) + } + + companion object { + val filterTypes = mutableMapOf>( + FluidType.javaClass.simpleName to FluidType, + ItemType.javaClass.simpleName to ItemType, + ) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt new file mode 100644 index 0000000000..eda60f3345 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt @@ -0,0 +1,17 @@ +package net.horizonsend.ion.server.features.transport.fluids + +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataType + +object FluidPersistentDataType : PersistentDataType { + override fun getComplexType(): Class = Fluid::class.java + override fun getPrimitiveType(): Class = String::class.java + + override fun fromPrimitive(primitive: String, context: PersistentDataAdapterContext): Fluid { + return FluidRegistry.get(primitive)!! + } + + override fun toPrimitive(complex: Fluid, context: PersistentDataAdapterContext): String { + return complex.identifier + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index e2aa4722a2..2b860a33d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -85,6 +85,9 @@ object NamespacedKeys { val GAS = key("Gas") val FILTER_DATA = key("filter_data") + val FILTER_TYPE = key("filter_type") + val FILTER_ENTRY = key("filter_entry") + val WHITELIST = key("whitelist") val POWER_TRANSPORT = key("power_transport") val FLUID_TRANSPORT = key("gas_transport") From 744e36bde8d4649f9f010f9a209617ff7871b80d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 13:08:44 -0600 Subject: [PATCH 360/500] upstream fixes --- .../features/starship/modules/PlayerShipSinkMessageFactory.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/modules/PlayerShipSinkMessageFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/modules/PlayerShipSinkMessageFactory.kt index c85d178918..d0c214b214 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/modules/PlayerShipSinkMessageFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/modules/PlayerShipSinkMessageFactory.kt @@ -8,6 +8,8 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.configuration.ConfigurationFiles +import net.horizonsend.ion.server.features.chat.Discord +import net.horizonsend.ion.server.features.chat.Discord.asDiscord import net.horizonsend.ion.server.features.progression.ShipKillXP import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.active.ActiveControlledStarship @@ -19,8 +21,6 @@ import net.horizonsend.ion.server.features.starship.damager.Damager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.ARENA_PREFIX -import net.horizonsend.ion.server.miscellaneous.utils.Discord -import net.horizonsend.ion.server.miscellaneous.utils.Discord.asDiscord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.empty From 096b23bfaaeda46d81640a893e3d9a1b59022776 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 13:09:11 -0600 Subject: [PATCH 361/500] re-register large tractor beam --- .../ion/server/features/multiblock/MultiblockRegistration.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 55475a37e5..21ec21f6a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -51,6 +51,7 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.DisposalMultiblo import net.horizonsend.ion.server.features.multiblock.type.misc.ExpandableAirlock import net.horizonsend.ion.server.features.multiblock.type.misc.FuelTankMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.ItemSplitterMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.LargeTractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender @@ -388,6 +389,7 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(AirlockMultiblock) registerMultiblock(ExpandableAirlock) registerMultiblock(TractorBeamMultiblock) + registerMultiblock(LargeTractorBeamMultiblock) registerMultiblock(AntiAirCannonBaseMultiblock) } From f1c7ca77721f4c6281212ffe9583dfb53d13e0bb Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 13:39:01 -0600 Subject: [PATCH 362/500] Check multiblock integrity when smacking a sign with a wrench --- .../server/command/misc/MultiblockCommand.kt | 1 - .../server/features/custom/items/misc/Wrench.kt | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 228407ad51..1eff700689 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -104,7 +104,6 @@ object MultiblockCommand : SLCommand() { if (!requirementMet) { val (xx, yy, zz) = Vec3i(relative.location) - sendEntityPacket(sender, displayBlock(sender.world.minecraft, requirement.getExample(face), Vector(xx, yy, zz), 0.5f, true), 10 * 20L) sender.userError( "Block at ${Vec3i(relative.location)} doesn't match! Expected ${requirement.alias}, found ${relative.type}." diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index f42a92ad94..82b4fcf2f1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -1,8 +1,12 @@ package net.horizonsend.ion.server.features.custom.items.misc +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text @@ -24,7 +28,20 @@ object Wrench : CustomItem("WRENCH") { } override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + if (livingEntity !is Player) return + + val hitBlock = event.clickedBlock + if (hitBlock?.type?.isWallSign != true) return + + val sign = hitBlock.state as? Sign ?: return + val multiblock = MultiblockAccess.getFast(sign) ?: return + + if (multiblock.signMatchesStructure(sign, loadChunks = false, particles = false)) { + livingEntity.information("Multiblock structure is correct.") + return + } + MultiblockCommand.onCheck(livingEntity, multiblock, sign.x, sign.y, sign.z) } override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { From 67e140a0c72058f8fc1e401f1c3eca7e6bf515d9 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 1 Dec 2024 13:56:52 -0600 Subject: [PATCH 363/500] remove unused function --- .../ion/server/features/custom/items/misc/Wrench.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index 82b4fcf2f1..9bccacf307 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -50,14 +50,9 @@ object Wrench : CustomItem("WRENCH") { val state = clickedBlock.state if (livingEntity.isSneaking && state is Sign) return tryPickUpMultiblock(livingEntity, state) - if (state is Sign) return tryEditFilter(livingEntity, state) } private fun tryPickUpMultiblock(player: Player, sign: Sign) { PrePackaged.pickUpStructure(player, sign) } - - private fun tryEditFilter(player: Player, sign: Sign) { // State TBD - - } } From 9d67aa442e640e87856aecbc28f7d2b3aa5a02b2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 3 Dec 2024 12:46:46 -0600 Subject: [PATCH 364/500] Add filter transport nodes --- .../custom/items/misc/TransportFilterItem.kt | 2 +- .../transport/filters/FilterAccess.kt | 4 +- .../transport/filters/FilterBlocks.kt | 22 ++++++---- .../nodes/cache/FluidTransportCache.kt | 11 ++++- .../transport/nodes/cache/NodeCacheFactory.kt | 41 ++++++++++++++++++- .../transport/nodes/types/FilterNode.kt | 5 +++ .../transport/nodes/types/FluidNode.kt | 27 +++++++----- 7 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FilterNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt index 83f322c5a2..ad0c1e7bd6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt @@ -16,7 +16,7 @@ import org.bukkit.inventory.meta.BlockStateMeta import org.bukkit.persistence.PersistentDataType.STRING import java.util.function.Supplier -class TransportFilterItem(identifier: String, val displayName: Component, private val filterBlock: Supplier) : CustomItem(identifier) { +class TransportFilterItem(identifier: String, val displayName: Component, private val filterBlock: Supplier>) : CustomItem(identifier) { override fun constructItemStack(): ItemStack { return ItemStack(Material.BARREL).updateMeta { meta -> meta as BlockStateMeta diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt index 16c40e9b95..4176580622 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt @@ -36,10 +36,10 @@ object FilterAccess : IonServerComponent() { val filterData = state.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) - type.openGUI(event.player, filterData) + type.openGUI(event.player, state, filterData) } - private fun tryDrop(block: Block, state: Barrel, type: FilterBlock) { + private fun tryDrop(block: Block, state: Barrel, type: FilterBlock<*>) { val dropLocation = block.location.toCenterLocation() val item = type.customItem.createFor(state) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt index 557ebf2faf..b58f1ad42d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt @@ -3,8 +3,10 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItems import net.horizonsend.ion.server.features.custom.items.misc.TransportFilterItem +import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FILTER_DATA import org.bukkit.Material import org.bukkit.block.Barrel import org.bukkit.entity.Player @@ -12,24 +14,24 @@ import org.bukkit.persistence.PersistentDataType.STRING import java.util.function.Supplier object FilterBlocks : IonServerComponent() { - private val filters = mutableMapOf() - fun all(): Map = filters + private val filters = mutableMapOf>() + fun all(): Map> = filters - fun getFilterBlock(state: Barrel): FilterBlock? { + fun getFilterBlock(state: Barrel): FilterBlock<*>? { val identifier = state.persistentDataContainer.get(CUSTOM_ITEM, STRING) ?: return null return filters[identifier] } - val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItems.FLUID_FILTER } + val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItems.FLUID_FILTER } - private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { - val data = FilterBlock(identifier, cacheType, customItemSupplier) + private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { + val data = FilterBlock(identifier, cacheType, customItemSupplier) filters[identifier] = data return data } } -class FilterBlock(val identifier: String, val cacheType: CacheType, private val customItemSupplier: Supplier) { +class FilterBlock(val identifier: String, val cacheType: CacheType, private val customItemSupplier: Supplier) { val customItem get() = customItemSupplier.get() fun createState(): Barrel { @@ -38,7 +40,11 @@ class FilterBlock(val identifier: String, val cacheType: CacheType, private val return baseState } - fun openGUI(player: Player, data: FilterData<*>?) { + fun openGUI(player: Player, state: Barrel, data: FilterData<*>?) { + if (data != null) { + state.persistentDataContainer.set(FILTER_DATA, FilterData, FilterData(false, mutableListOf())) + } + println("$player $data") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 542b2c252b..4eed3f8aa7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -3,9 +3,12 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.filters.FilterBlocks +import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.types.FilterNode import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode @@ -40,6 +43,10 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) .addSimpleNode(Material.IRON_BLOCK, FluidNode.FluidMergeNode) .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) + .addFilterHandler(FilterBlocks.FLUID_FILTER) { data, location -> + @Suppress("UNCHECKED_CAST") + FluidNode.FluidFilterNode(data as FilterData, location) + } .build() override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { @@ -98,7 +105,9 @@ class FluidTransportCache(holder: CacheHolder): TransportCa val numDestinations = filteredDestinations.size val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, filteredDestinations[it]) { node, _ -> node is FluidNode && node.canTransport(fluid) } + getIdealPath(source, filteredDestinations[it]) { node, _ -> + (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) ?: true) + } }.getOrNull() } var maximumResistance: Double = -1.0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 102efb7167..da013fe0ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,18 +1,30 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.features.transport.filters.FilterBlock +import net.horizonsend.ion.server.features.transport.filters.FilterBlocks +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.nodes.types.FilterNode import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe import org.bukkit.Material +import org.bukkit.block.Barrel import org.bukkit.block.Block import org.bukkit.block.data.BlockData import kotlin.reflect.KClass -class NodeCacheFactory private constructor(private val materialHandlers: Map>) { +class NodeCacheFactory private constructor(private val materialHandlers: Map>, private val filterConstructor: FilterConstructor<*>?) { fun cache(block: Block): Node? { val type = block.getTypeSafe() ?: return null + + if (filterConstructor != null) { + val result = tryCacheFilter(block) + if (result != null) return result + } + val materialFactory = materialHandlers[type] ?: return null val blockData = getBlockDataSafe(block.world, block.x, block.y, block.z) ?: return null @@ -20,8 +32,21 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map? { + filterConstructor!! + val barrel = block.state as? Barrel ?: return null + if (FilterBlocks.getFilterBlock(barrel) != filterConstructor.filterType) return null + + val pdc = barrel.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) + return filterConstructor.construct(pdc, toBlockKey(block.x, block.y, block.z)) + } + class Builder { val materialHandlers = mutableMapOf>() + private var filterHandler: FilterConstructor<*>? = null inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node): Builder { this.materialHandlers[material] = MaterialHandler(T::class, constructor) @@ -48,8 +73,13 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map addFilterHandler(filterType: FilterBlock, constructor: (FilterData<*>?, BlockKey) -> FilterNode): Builder { + this.filterHandler = FilterConstructor(filterType, constructor) + return this + } + fun build(): NodeCacheFactory { - return NodeCacheFactory(materialHandlers) + return NodeCacheFactory(materialHandlers, filterHandler) } } @@ -61,6 +91,13 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val filterType: FilterBlock, val constructor: (FilterData<*>?, BlockKey) -> FilterNode) { + @Synchronized + fun construct(blockData: FilterData<*>?, key: BlockKey): FilterNode { + return constructor.invoke(blockData, key) + } + } + companion object { fun builder(): Builder = Builder() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FilterNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FilterNode.kt new file mode 100644 index 0000000000..c297ba7bd3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FilterNode.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.transport.nodes.types + +interface FilterNode : Node { + fun canTransfer(resource: T): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt index 2ccef0554a..c21129c46f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -17,17 +18,11 @@ import org.bukkit.block.BlockFace sealed interface FluidNode : Node { override val cacheType: CacheType get() = CacheType.FLUID - /** - * Used for filters - **/ - fun canTransport(fluid: Fluid): Boolean - data class FluidJunctionNode(val channel: Material) : FluidNode { override val pathfindingResistance: Double = 1.0 override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = if (other is FluidJunctionNode) other.channel == channel else true override fun canTransferTo(other: Node, offset: BlockFace): Boolean = if (other is FluidJunctionNode) other.channel == channel else true override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun canTransport(fluid: Fluid): Boolean = true } data class LightningRodNode(var axis: Axis) : FluidNode, ComplexNode { @@ -38,7 +33,6 @@ sealed interface FluidNode : Node { override fun onTranslate(movement: StarshipMovement) { this.axis = movement.displaceFace(this.axis.faces.first).axis } - override fun canTransport(fluid: Fluid): Boolean = true } data object FluidExtractorNode : FluidNode { @@ -46,7 +40,6 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is FluidInputNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun canTransport(fluid: Fluid): Boolean = true } data object FluidInputNode : FluidNode { @@ -54,7 +47,6 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun canTransport(fluid: Fluid): Boolean = true fun getFluidEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.FLUID, location).filterIsInstance() } @@ -63,7 +55,6 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is FluidJunctionNode override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is FluidJunctionNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun canTransport(fluid: Fluid): Boolean = true } data object FluidInvertedMergeNode : FluidNode { @@ -71,6 +62,20 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is LightningRodNode override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is LightningRodNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun canTransport(fluid: Fluid): Boolean = true + } + + data class FluidFilterNode(val filterData: FilterData?, val location: BlockKey) : FluidNode, FilterNode { + override val pathfindingResistance: Double = 1.0 + + override fun canTransfer(resource: Fluid): Boolean { + if (filterData == null) return true + val containsEntry = filterData.entries.any { it.entry == resource } + + return filterData.isWhitelist == containsEntry + } + + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true } } From 3d084c597f8c1676605a5ca7ac234484d4325511 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Dec 2024 14:09:12 -0600 Subject: [PATCH 365/500] capture nodes & extractors when ship pilots, delete old extractors --- .../command/misc/TransportDebugCommand.kt | 7 - .../features/starship/PilotedStarships.kt | 18 -- .../ion/server/features/starship/Starship.kt | 4 +- .../transport/manager/ShipTransportManager.kt | 18 +- .../extractors/ShipExtractorManager.kt | 34 ++- .../manager/holders/ShipCacheHolder.kt | 20 ++ .../transport/nodes/cache/TransportCache.kt | 16 +- .../transport/nodes/types/ComplexNode.kt | 2 +- .../transport/nodes/types/FluidNode.kt | 2 +- .../transport/nodes/types/PowerNode.kt | 4 +- .../features/transport/old/Extractors.kt | 285 ------------------ .../features/transport/old/pipe/Pipes.kt | 5 +- .../miscellaneous/registrations/Components.kt | 2 - 13 files changed, 87 insertions(+), 330 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index fe3ce2af8a..541f47342f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -7,7 +7,6 @@ import io.papermc.paper.util.StacktraceDeobfuscator import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks -import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion @@ -29,12 +28,6 @@ object TransportDebugCommand : SLCommand() { sender.success("Reloaded config") } - @Suppress("Unused") - @Subcommand("clearbusy") - fun onClearBusy(sender: CommandSender) { - Extractors.BUSY_PIPE_EXTRACTORS.clear() - } - @Subcommand("dump inputs") fun dumpInputs(sender: Player, type: CacheType) { val inputManager = sender.world.ion.inputManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt index cfb5200a66..2efa082a10 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/PilotedStarships.kt @@ -40,7 +40,6 @@ import net.horizonsend.ion.server.features.starship.subsystem.misc.MiningLaserSu import net.horizonsend.ion.server.features.starship.subsystem.reactor.ReactorSubsystem import net.horizonsend.ion.server.features.starship.subsystem.shield.ShieldSubsystem import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields -import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.actualType @@ -57,7 +56,6 @@ import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.minimessage.MiniMessage import org.bukkit.Bukkit -import org.bukkit.Material import org.bukkit.World import org.bukkit.block.data.BlockData import org.bukkit.boss.BarColor @@ -119,8 +117,6 @@ object PilotedStarships : IonServerComponent() { StarshipShields.updateShieldBars(starship) - removeExtractors(starship) - callback(starship) } @@ -185,14 +181,6 @@ object PilotedStarships : IonServerComponent() { } } - private fun removeExtractors(starship: ActiveControlledStarship) { - starship.iterateBlocks { x, y, z -> - if (starship.world.getBlockAt(x, y, z).type == Material.CRAFTING_TABLE) { - Extractors.remove(starship.world, Vec3i(x, y, z)) - } - } - } - fun isPiloted(starship: ActiveControlledStarship): Boolean { if (starship.controller is UnpilotedController) return false if (starship.controller is NoOpController) return false @@ -226,12 +214,6 @@ object PilotedStarships : IonServerComponent() { starship.shieldBars.values.forEach { it.removeAll() } starship.shieldBars.clear() - starship.iterateBlocks { x, y, z -> - if (starship.world.getBlockAt(x, y, z).type == Material.CRAFTING_TABLE) { - Extractors.add(starship.world, Vec3i(x, y, z)) - } - } - StarshipUnpilotedEvent(starship, controller, unpilotedController).callEvent() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt index d9004b9e1e..7e4cdc0c7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/Starship.kt @@ -172,9 +172,9 @@ class Starship( //endregion // Start region transport - val multiblockManager = ShipMultiblockManager(this) - val transportManager = ShipTransportManager(this) + + val multiblockManager = ShipMultiblockManager(this) // Endregion //region Ship Blocks & Hitbox diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 3cccfb3f61..1dd388f5e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -4,7 +4,6 @@ import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager -import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.manager.holders.ShipCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache @@ -17,7 +16,7 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { private val inputManager = ShipInputManager(this) override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } - override val solarPanelManager: CacheHolder = ShipCacheHolder(this) { SolarPanelCache(it) } + override val solarPanelManager: ShipCacheHolder = ShipCacheHolder(this) { SolarPanelCache(it) } override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } init { @@ -25,17 +24,26 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { } fun load() { - NewTransport.registerTransportManager(this) + powerNodeManager.capture() + solarPanelManager.capture() + fluidNodeManager.capture() extractorManager.loadExtractors() + NewTransport.registerTransportManager(this) } fun release() { - NewTransport.removeTransportManager(this) + powerNodeManager.release() + solarPanelManager.release() + fluidNodeManager.release() extractorManager.releaseExtractors() + NewTransport.removeTransportManager(this) } fun displace(movement: StarshipMovement) { - + powerNodeManager.displace(movement) + solarPanelManager.displace(movement) + fluidNodeManager.displace(movement) + extractorManager.displace(movement) } override fun getInputProvider(): InputManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index 30a9d7dcaf..46533dbb51 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -2,12 +2,18 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.starship.Starship +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe class ShipExtractorManager(val starship: Starship) : ExtractorManager() { - val extractors = Long2ObjectOpenHashMap() + var extractors = Long2ObjectOpenHashMap() override fun getExtractors(): Collection { return extractors.values @@ -17,6 +23,7 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { return extractors.contains(key) } + /** Returns true if an extractor was registered */ override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { if (ensureExtractor && getBlockTypeSafe(starship.world, x, y, z) != EXTRACTOR_TYPE) return false val key = toBlockKey(x, y, z) @@ -33,10 +40,31 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { } fun loadExtractors() { - starship.iterateBlocks { x, y, z -> registerExtractor(x, y, z, true) } + starship.iterateBlocks { x, y, z -> + if (registerExtractor(x, y, z, true)) NewTransport.removeExtractor(starship.world, x, y, z) + } } fun releaseExtractors() { - //TODO + // We can disregard the extractor data + // Its more so a convenience thing + val byChunk = extractors.keys.groupBy { key -> + chunkKey(getX(key).shr(4), getZ(key).shr(4)) + } + + for ((chunkKey, entries) in byChunk) { + val ionChunk = IonChunk[starship.world, chunkKey] ?: continue + + for (entry in entries) { + ionChunk.transportNetwork.extractorManager.registerExtractor(entry, ensureExtractor = true) + } + } + } + + fun displace(movement: StarshipMovement) { + val new = Long2ObjectOpenHashMap() + extractors.forEach { new[movement.displaceKey(it.key)] = it.value } + + extractors = new } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 141c0613ad..1a627070da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.transport.manager.holders import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache @@ -43,4 +45,22 @@ class ShipCacheHolder(override val transportManager: ShipTran override fun getExtractorManager(): ExtractorManager { return transportManager.extractorManager } + + fun capture() { + transportManager.starship.iterateBlocks { x, y, z -> + NewTransport.invalidateCache(getWorld(), x, y, z) + + cache.cache(toBlockKey(x, y, z)) + } + } + + fun displace(movement: StarshipMovement) { + cache.displace(movement) + } + + fun release() { + transportManager.starship.iterateBlocks { x, y, z -> + NewTransport.invalidateCache(getWorld(), x, y, z) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 0c62c3e106..8a1f8d75c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -3,7 +3,9 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.types.ComplexNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType @@ -24,7 +26,7 @@ import org.bukkit.block.BlockFace import java.util.concurrent.ConcurrentHashMap abstract class TransportCache(val holder: CacheHolder<*>) { - private val cache: ConcurrentHashMap = ConcurrentHashMap() + private var cache: ConcurrentHashMap = ConcurrentHashMap() abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory @@ -70,6 +72,18 @@ abstract class TransportCache(val holder: CacheHolder<*>) { fun getRawCache() = cache + fun displace(movement: StarshipMovement) { + val new = ConcurrentHashMap() + + for ((key, cached) in new) { + val newKey = movement.displaceKey(key) + if (cached is ComplexNode) cached.displace(movement) + new[newKey] = cached + } + + cache = new + } + /** * Gets the powered entities accessible from this location, assuming it is an input * This method is used in conjunction with input registration to allow direct access via signs, and remote access via registered inputs diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt index d3964749ff..00517a8aa4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ComplexNode.kt @@ -3,5 +3,5 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.starship.movement.StarshipMovement interface ComplexNode { - fun onTranslate(movement: StarshipMovement) + fun displace(movement: StarshipMovement) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt index c21129c46f..90ad2b63d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt @@ -30,7 +30,7 @@ sealed interface FluidNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) - override fun onTranslate(movement: StarshipMovement) { + override fun displace(movement: StarshipMovement) { this.axis = movement.displaceFace(this.axis.faces.first).axis } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 00b0539a71..e991b24514 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -36,7 +36,7 @@ sealed interface PowerNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) - override fun onTranslate(movement: StarshipMovement) { + override fun displace(movement: StarshipMovement) { this.axis = movement.displaceFace(this.axis.faces.first).axis } } @@ -146,7 +146,7 @@ sealed interface PowerNode : Node { displayHandler.remove() } - override fun onTranslate(movement: StarshipMovement) { + override fun displace(movement: StarshipMovement) { this.face = movement.displaceFace(this.face) displayHandler.displace(movement) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt deleted file mode 100644 index 89f74b67ea..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/Extractors.kt +++ /dev/null @@ -1,285 +0,0 @@ -package net.horizonsend.ion.server.features.transport.old - -import com.google.gson.Gson -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.old.pipe.Pipes -import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData -import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters -import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES -import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe -import net.horizonsend.ion.server.miscellaneous.utils.getStateIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.gzip -import net.horizonsend.ion.server.miscellaneous.utils.listen -import net.horizonsend.ion.server.miscellaneous.utils.randomEntry -import net.horizonsend.ion.server.miscellaneous.utils.ungzip -import org.bukkit.Bukkit.shutdown -import org.bukkit.Material -import org.bukkit.World -import org.bukkit.block.BlockFace -import org.bukkit.block.BlockState -import org.bukkit.block.data.BlockData -import org.bukkit.block.data.type.DaylightDetector -import org.bukkit.event.world.WorldLoadEvent -import org.bukkit.event.world.WorldUnloadEvent -import org.bukkit.inventory.InventoryHolder -import java.io.File -import java.nio.file.Files -import java.util.concurrent.ConcurrentHashMap -import kotlin.collections.set - -object Extractors : IonServerComponent() { - - private val worldDataMap = ConcurrentHashMap>() - - val BUSY_PIPE_EXTRACTORS: MutableSet = ConcurrentHashMap.newKeySet() - - override fun onEnable() { - return - IonServer.server.worlds.forEach(Extractors::loadExtractors) - listen { event -> loadExtractors(event.world) } - listen { event -> unloadExtractors(event.world) } - } - - override fun onDisable() { - IonServer.server.worlds.forEach(Extractors::unloadExtractors) - } - - //region Loading and saving - private fun getDataFile(world: World): File = File(world.worldFolder, "data/starlegacy/extractors.json.gz") - .apply { parentFile.mkdirs() } - - data class WorldDataStorage(val values: List) - - private fun loadExtractors(world: World) { - val file: File = getDataFile(world) - - val worldData: WorldDataStorage - - val exists: Boolean = file.exists() - - worldData = if (exists) { - try { - Gson().fromJson(ungzip(Files.readAllBytes(file.toPath())), WorldDataStorage::class.java) - } catch (e: Exception) { - e.printStackTrace() - log.error("Failed to load extractors for ${world.name}, to be safe, the server will now shutdown to prevent loss of data, please correct the issue if possible.") - shutdown() - return - } - } else { - WorldDataStorage(listOf()) - } - - worldDataMap[world] = ConcurrentHashMap.newKeySet().apply { addAll(worldData.values) } - - if (exists) { - log.debug("Loaded extractors for world ${world.name}") - } else { - saveExtractors(world) - log.info("Created extractors file for word ${world.name}") - } - } - - private fun saveExtractors(world: World) { - val file = getDataFile(world) - - val values: Set = worldDataMap[world] ?: error("No data for world ${world.name}, but tried to save!") - - val worldData = WorldDataStorage(values.toList()) - - val bytes = gzip(Gson().toJson(worldData)) - val oldFile = File(file.parent, file.name + ".old") - file.renameTo(oldFile) - Files.write(file.toPath(), bytes) - oldFile.delete() - - log.debug("Saved extractor data for world ${world.name}") - } - - private fun unloadExtractors(world: World) { - saveExtractors(world) - worldDataMap.remove(world) - } - //endregion - - private fun tickExtractors(world: World) { - val extractorLocations: Set = worldDataMap[world] ?: return - - extractorLoop@ for (extractorLocation: Vec3i in extractorLocations) { - val (x: Int, y: Int, z: Int) = extractorLocation - - // note on continuing for null values: if it is null that means - // the chunk is unloaded or something, so we ignore the extractor - - // eventually, make this auto remove when it's been invalid for a long time. for now, just ignore it - // this also ensures the chunk is loaded - val extractorMaterial: Material? = getBlockTypeSafe(world, x, y, z) - - if (extractorMaterial != ExtractorManager.EXTRACTOR_TYPE) { - continue - } - - val computers: MutableSet = mutableSetOf() // list of note block power machine computers - val wires: MutableSet = mutableSetOf() // list of end rod wires - val inventories: MutableSet = mutableSetOf() // list of inventories to extract from to pipes - val pipes: MutableSet = mutableSetOf() // list of pipes to extract to - - var solarSensor: BlockData? = null - - // check adjacent blocks & fill the lists with them - adjacentCheck@ - for (face: BlockFace in ADJACENT_BLOCK_FACES) { - val adjacentX: Int = x + face.modX - val adjacentY: Int = y + face.modY - val adjacentZ: Int = z + face.modZ - - val adjacentType: Material = getBlockTypeSafe(world, adjacentX, adjacentY, adjacentZ) - ?: continue - - when { - isExtractableInventory(adjacentType) -> { - inventories.add(Vec3i(adjacentX, adjacentY, adjacentZ)) - } - - Pipes.isAnyPipe(adjacentType) -> { - pipes.add(face) - } - - adjacentType == Wires.INPUT_COMPUTER_BLOCK -> { - computers.add(Vec3i(adjacentX, adjacentY, adjacentZ)) - } - - Wires.isAnyWire(adjacentType) -> { - wires.add(face) - } - - adjacentType == Material.DIAMOND_BLOCK && face == BlockFace.UP -> { - val sensor: BlockData = getBlockDataSafe(world, adjacentX, adjacentY + 1, adjacentZ) - ?: continue@extractorLoop - - if (sensor.material == Material.DAYLIGHT_DETECTOR) { - solarSensor = sensor - } - } - } - } - - // if there is an inventory and a pipe and it was not already busy, handle it - if (inventories.isNotEmpty() && pipes.isNotEmpty() && BUSY_PIPE_EXTRACTORS.add(extractorLocation)) { - handlePipe(world, extractorLocation, inventories, pipes) - } - - if (computers.isNotEmpty() && wires.isNotEmpty()) { - handleWire(world, x, y, z, computers, wires) - } - - if (solarSensor != null) { - handleSolarPanel(world, x, y, z, wires, solarSensor) - } - } - } - - private fun isExtractableInventory(adjacentType: Material): Boolean { - return Pipes.isPipedInventory(adjacentType) || - adjacentType == Material.HOPPER - } - - // TODO: Make this mostly async - private fun handlePipe(world: World, extractorLocation: Vec3i, inventoryLocations: Set, pipeLocations: Set) = Tasks.sync { - var cancelled = true - - try { - val (x, y, z) = extractorLocation - - val filteredItemMap = mutableMapOf>() - - // filter it to only locations that are still loaded, - // still inventory blocks, and have items in their inventory - val inventories: List = inventoryLocations.filter { invPos -> - val (invX: Int, invY: Int, invZ: Int) = invPos - val state: BlockState = getStateIfLoaded(world, invX, invY, invZ) - ?: return@filter false // ignore it if the chunk isn't loaded - - if (!isExtractableInventory(state.type)) { - return@filter false - } - - val inventory = (state as InventoryHolder).inventory - val filtered = Filters.getItemData(inventory) - filteredItemMap[invPos] = filtered - // check that at least one item is not null - return@filter filtered.any() - } - - if (inventories.isEmpty()) { - return@sync - } - - // filter it to only locations that are still loaded and pipe blocks - val pipes = pipeLocations.filter { face -> - val type: Material = getBlockTypeSafe(world, x + face.modX, y + face.modY, z + face.modZ) - ?: return@filter false - - return@filter Pipes.isAnyPipe(type) - } - - if (pipes.isEmpty()) { - return@sync - } - - val pipe: BlockFace = pipes.randomEntry() - val inventory: Vec3i = inventories.randomEntry() - - val filteredItems = filteredItemMap.getValue(inventory) - Pipes.startPipeChain(world, x, y, z, pipe, inventory, extractorLocation, filteredItems) - cancelled = false - } finally { - if (cancelled) { - BUSY_PIPE_EXTRACTORS.remove(extractorLocation) - } - } - } - - private fun handleWire(world: World, x: Int, y: Int, z: Int, computers: Set, wires: Set) { - val wire: BlockFace = wires.randomEntry() - val computer: Vec3i = computers.randomEntry() - - Wires.startWireChain(world, x, y, z, wire, computer) - } - - private fun handleSolarPanel(world: World, x: Int, y: Int, z: Int, wires: Set, sensor: BlockData) { - if (wires.isEmpty()) { - return - } - - sensor as DaylightDetector - val inverted: Boolean = sensor.isInverted - val power: Int = sensor.power - - if (!inverted && power > 6 && world.environment == World.Environment.NORMAL || - inverted && world.environment != World.Environment.NORMAL) { - Wires.startWireChain(world, x, y, z, wires.randomEntry(), null) - } - } - - private fun getExtractorSet(world: World): MutableSet { - return worldDataMap[world] ?: error("No extractors loaded for ${world.name}") - } - - fun add(world: World, coordinates: Vec3i): Boolean { - return getExtractorSet(world).add(coordinates) - } - - fun remove(world: World, coordinates: Vec3i): Boolean { - return getExtractorSet(world).remove(coordinates) - } - - fun contains(world: World, coordinates: Vec3i): Boolean { - return getExtractorSet(world).contains(coordinates) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt index 9957033074..23ff70c864 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer import net.horizonsend.ion.server.features.machine.GeneratorFuel -import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterData import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters @@ -97,7 +96,7 @@ object Pipes : IonServerComponent() { while (!inventoryCheckTasks.isEmpty()) { val task = inventoryCheckTasks.poll() val data = task.data - Extractors.BUSY_PIPE_EXTRACTORS.remove(data.extractor) +// Extractors.BUSY_PIPE_EXTRACTORS.remove(data.extractor) pending.decrementAndGet() val world = data.world worldCounts.getOrPut(world, ::AtomicInteger).incrementAndGet() @@ -523,7 +522,7 @@ object Pipes : IonServerComponent() { private fun queueNotBusy(extractor: Vec3i) { Tasks.syncDelay(5) { - Extractors.BUSY_PIPE_EXTRACTORS.remove(extractor) +// Extractors.BUSY_PIPE_EXTRACTORS.remove(extractor) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index c1020867ec..2a775fb649 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -94,7 +94,6 @@ import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.filters.FilterAccess import net.horizonsend.ion.server.features.transport.filters.FilterBlocks import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry -import net.horizonsend.ion.server.features.transport.old.Extractors import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes @@ -152,7 +151,6 @@ val components: List = listOf( FilterBlocks, FilterAccess, TransportConfig.Companion, - Extractors, Pipes, Filters, Wires, From 7fc46e20d8e71a93ba75ef25c33a6dfefe25aefa Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Dec 2024 18:05:43 -0600 Subject: [PATCH 366/500] capture nodes & extractors when ship pilots, delete old extractors --- .../display/modular/TextDisplayHandler.kt | 6 +- .../client/display/modular/display/Display.kt | 43 ++++++++----- .../modular/display/FlowMeterDisplay.kt | 25 ++++++++ .../multiblock/entity/MultiblockEntity.kt | 27 ++++---- .../entity/type/fluids/FluidStoringEntity.kt | 6 -- .../type/power/PoweredMultiblockEntity.kt | 9 --- .../entity/type/power/SimplePoweredEntity.kt | 19 ++---- .../manager/ChunkMultiblockManager.kt | 1 + .../multiblock/manager/MultiblockManager.kt | 21 +++++++ .../manager/ShipMultiblockManager.kt | 18 +----- .../type/fluid/CanisterVentMultiblock.kt | 3 + .../type/fluid/ElectrolysisMultiblock.kt | 24 ++------ .../CanisterGasCollectorMultiblock.kt | 3 + .../collector/PipedGasCollectorMultiblock.kt | 17 ++---- .../fluid/storage/FluidStorageMultiblock.kt | 19 ++---- .../type/misc/ItemSplitterMultiblock.kt | 2 + .../multiblock/type/misc/MobDefender.kt | 3 + .../type/power/storage/PowerCellMultiblock.kt | 5 +- .../transport/nodes/cache/TransportCache.kt | 7 ++- .../transport/nodes/inputs/InputsData.kt | 61 +++++++++++++++++++ 20 files changed, 194 insertions(+), 125 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index d8ba58c803..46a46edc1d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -46,7 +46,7 @@ class TextDisplayHandler( fun register(): TextDisplayHandler { displays.forEach { - it.setParent(this) + it.initialize(this) it.register() } @@ -58,9 +58,9 @@ class TextDisplayHandler( fun getLocation(): Location { val rightFace = if (facing.axis == Axis.Y) BlockFace.NORTH else facing.rightFace - val offsetX = rightFace.modX * offsetRight + facing.modX * offsetForward + val offsetX = (rightFace.modX * offsetRight) + (facing.modX * offsetForward) val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetRight + facing.modZ * offsetForward + val offsetZ = (rightFace.modZ * offsetRight) + (facing.modZ * offsetForward) return Location(world, anchorX + offsetX, anchorY + offsetY, anchorZ + offsetZ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index 6ddc91863c..4c472797a1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -16,7 +16,6 @@ import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Display.TextDisplay import net.minecraft.world.entity.EntityType import org.bukkit.Axis.Y -import org.bukkit.Bukkit import org.bukkit.Bukkit.getPlayer import org.bukkit.Color import org.bukkit.block.BlockFace @@ -30,7 +29,7 @@ import java.util.UUID abstract class Display( private val offsetRight: Double, private val offsetUp: Double, - private val offsetBack: Double, + private val offsetForward: Double, val scale: Float ) { var shownPlayers = mutableSetOf() @@ -57,30 +56,42 @@ abstract class Display( ) } - fun setParent(parent: TextDisplayHandler) { + private var isInitializing = false + + val mutex = Any() + + fun initialize(parent: TextDisplayHandler) = synchronized(mutex) { + if (isInitializing || this::handler.isInitialized) { + return@synchronized + } + + isInitializing = true + this.handler = parent val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace - val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetBack + val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetForward val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetRight + parent.facing.modZ * offsetBack + val offsetZ = rightFace.modZ * offsetRight + parent.facing.modZ * offsetForward val parentLoc = parent.getLocation() - entity = createEntity(parent).getNMSData( - parentLoc.x + offsetX, - parentLoc.y + offsetY, - parentLoc.z + offsetZ - ) + runCatching { + entity = createEntity(parent).getNMSData( + parentLoc.x + offsetX, + parentLoc.y + offsetY, + parentLoc.z + offsetZ + ) + } } fun resetPosition(parent: TextDisplayHandler) { val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace - val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetBack + val offsetX = (rightFace.modX * offsetRight) + (parent.facing.modX * offsetForward) val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetRight + parent.facing.modZ * offsetBack + val offsetZ = (rightFace.modZ * offsetRight) + (parent.facing.modZ * offsetForward) val parentLoc = parent.getLocation() @@ -112,15 +123,15 @@ abstract class Display( entity.text = PaperAdventure.asVanilla(text) } - fun remove() { - for (shownPlayer in shownPlayers) Bukkit.getPlayer(shownPlayer)?.minecraft?.connection?.send( + open fun remove() { + for (shownPlayer in shownPlayers) getPlayer(shownPlayer)?.minecraft?.connection?.send( ClientboundRemoveEntitiesPacket(entity.id) ) shownPlayers.clear() } - fun display() { + open fun display() { if (!::handler.isInitialized) return update() @@ -128,7 +139,7 @@ abstract class Display( private val distSquared = (50.0 * 50.0) - fun update() { + open fun update() { setText(getText()) val chunk = entity.level().world.getChunkAtIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index 69b7fcffec..4f0abdceed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -2,12 +2,14 @@ package net.horizonsend.ion.server.features.client.display.modular.display import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay class FlowMeterDisplay( private val meter: PowerNode.PowerFlowMeter, @@ -27,4 +29,27 @@ class FlowMeterDisplay( val firstLine = text("E: ", YELLOW) val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Sec", GREEN)) } + + override fun createEntity(parent: TextDisplayHandler): CraftTextDisplay { + Throwable().printStackTrace() + + println("Create entity $this") + return super.createEntity(parent) + } + + @Synchronized + override fun display() { + println("Display") + super.display() + } + + override fun remove() { + println("Remove") + super.remove() + } + + override fun update() { + println("Update") + super.update() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 18405e30aa..9139712044 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.linkages.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -85,6 +85,7 @@ abstract class MultiblockEntity( fun processRemoval() { removed = true + releaseInputs() handleRemoval() if (this is DisplayMultiblockEntity) displayHandler.remove() removeLinkages() @@ -102,6 +103,7 @@ abstract class MultiblockEntity( open fun onUnload() {} fun processLoad() { + registerInputs() if (this is DisplayMultiblockEntity) displayHandler.update() onLoad() } @@ -211,6 +213,10 @@ abstract class MultiblockEntity( return getRelative(vec3i, structureDirection, right = right, up = up, forward = forward) } + fun getKeyRelative(right: Int, up: Int, forward: Int): BlockKey { + return toBlockKey(getRelative(vec3i, structureDirection, right = right, up = up, forward = forward)) + } + fun getInventory(right: Int, up: Int, forward: Int): Inventory? { return (getBlockRelative( right = right, up = up, forward = forward).getState(false) as? InventoryHolder)?.inventory } @@ -315,20 +321,19 @@ abstract class MultiblockEntity( } // Section inputs - fun registerInputs(type: CacheType, locations: Set) { - val inputManager = manager.getInputManager() - for (location in locations) { - inputManager.registerInput(type, toBlockKey(location), this) - } + abstract val inputsData: InputsData + + fun registerInputs() { + inputsData.registerInputs() } - fun releaseInputs(type: CacheType, locations: Set) { - val inputManager = manager.getInputManager() - for (location in locations) { - inputManager.deRegisterInput(type, toBlockKey(location), this) - } + fun releaseInputs() { + inputsData.releaseInputs() } + // Util + protected fun none(): InputsData = InputsData.builder(this).build() + val linkages = mutableMapOf() protected fun registerLinkage(right: Int, up: Int, forward: Int, linkageDirection: RelativeFace, allowedEntities: Array>): Supplier { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 02f32c161f..659f1ff556 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -16,12 +16,6 @@ import org.bukkit.persistence.PersistentDataType.TAG_CONTAINER interface FluidStoringEntity { val fluidStores: Array - val fluidInputOffsets: Array - - fun getFluidInputLocations(): Set { - this as MultiblockEntity - return fluidInputOffsets.mapTo(mutableSetOf()) { (right, up, forward) -> getPosRelative(right, up, forward) } - } /** * Returns the first capacity, if one is available, that can store the fluid stack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt index b9edfbf17b..98e26bcbf0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/PoweredMultiblockEntity.kt @@ -1,22 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.persistence.PersistentDataType interface PoweredMultiblockEntity { val powerStorage: PowerStorage val maxPower: Int - val powerInputOffsets: Array - - fun getPowerInputLocations(): Set { - this as MultiblockEntity - return powerInputOffsets.mapTo(mutableSetOf()) { (right, up, forward) -> getPosRelative(right, up, forward) } - } - fun loadStoredPower(data: PersistentMultiblockData): PowerStorage { return PowerStorage(this, data.getAdditionalDataOrDefault(NamespacedKeys.POWER, PersistentDataType.INTEGER, 0), maxPower) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index dc334f9800..a616443418 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -8,9 +8,8 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.persistence.PersistentDataAdapterContext @@ -27,8 +26,6 @@ abstract class SimplePoweredEntity( structureDirection: BlockFace, final override val maxPower: Int ) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { - override val powerInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) - @Suppress("LeakingThis") // Only a reference is needed, max power is provided in the constructor final override val powerStorage: PowerStorage = PowerStorage( this, @@ -45,15 +42,7 @@ abstract class SimplePoweredEntity( PowerEntityDisplay(entity, +0.0, +0.0, +0.0, 0.5f) ).register() - override fun onLoad() { - registerInputs(CacheType.POWER, getPowerInputLocations()) - } - - override fun handleRemoval() { - releaseInputs(CacheType.POWER, getPowerInputLocations()) - } - - override fun onUnload() { - releaseInputs(CacheType.POWER, getPowerInputLocations()) - } + override val inputsData: InputsData = InputsData.Builder(this) + .addPowerInput(0, -1, 0) + .build() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index e6cd7e0557..1624d686ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -103,6 +103,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag fun onUnload() { multiblockEntities.values.forEach { + it.releaseInputs() it.onUnload() if (it is DisplayMultiblockEntity) it.displayHandler.remove() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index e2e69f9a9e..1a21cf937c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing @@ -145,5 +146,25 @@ abstract class MultiblockManager(val log: Logger) { } fun isOccupied(x: Int, y: Int, z: Int): Boolean = multiblockEntities.containsKey(toBlockKey(x, y, z)) + + fun handleTransfer(location: BlockKey, destination: MultiblockManager) { + val atLocation = get(location) ?: return + atLocation.releaseInputs() + atLocation.manager = this + multiblockEntities.remove(location) + + destination.multiblockEntities[location] = atLocation + atLocation.registerInputs() + + if (atLocation is SyncTickingMultiblockEntity) { + destination.syncTickingMultiblockEntities[location] = atLocation + syncTickingMultiblockEntities.remove(location) + } + + if (atLocation is AsyncTickingMultiblockEntity) { + destination.asyncTickingMultiblockEntities[location] = atLocation + asyncTickingMultiblockEntities.remove(location) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index eef4e12acc..5fa0b37d4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -70,21 +70,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe val modernBlockKey = toBlockKey(x, y, z) val manager = worldManager.getChunkManager(modernBlockKey) ?: return@iterateBlocks - manager.getAllMultiblockEntities()[modernBlockKey]?.let { - multiblockEntities[modernBlockKey] = it - it.manager = this - manager.getAllMultiblockEntities().remove(modernBlockKey) - } ?: return@iterateBlocks - - manager.syncTickingMultiblockEntities[modernBlockKey]?.let { - syncTickingMultiblockEntities[modernBlockKey] = it - manager.syncTickingMultiblockEntities.remove(modernBlockKey) - } - - manager.asyncTickingMultiblockEntities[modernBlockKey]?.let { - asyncTickingMultiblockEntities[modernBlockKey] = it - manager.asyncTickingMultiblockEntities.remove(modernBlockKey) - } + manager.handleTransfer(modernBlockKey, this) } } @@ -93,7 +79,7 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe releaseEntities() } - fun releaseEntities() { + private fun releaseEntities() { val worldManager = world.ion.multiblockManager for ((key, multiblockEntity) in multiblockEntities) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt index 18a48daca0..9e6bb17390 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.World @@ -72,5 +73,7 @@ object CanisterVentMultiblock : Multiblock(), EntityMultiblock = arrayOf(Vec3i(-2, -1, 1), Vec3i(+2, -1, 1)) - override val powerInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) - override val powerStorage: PowerStorage = loadStoredPower(data) override val fluidStores: Array = arrayOf( @@ -243,20 +240,11 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock = arrayOf(Vec3i(0, -1, 0)) override val fluidStores: Array = arrayOf( loadStoredResource(data, "tank_1", text("Tank 1"), TANK_1, CategoryRestrictedInternalStorage(500, inputAllowed = false, extractionAllowed = true, GAS)), @@ -125,17 +124,9 @@ object PipedGasCollectorMultiblock : Multiblock(), SimpleFluidDisplay(getNamedStorage("tank_3"), +0.0, -0.10, 0.0, 0.45f) ).register() - override fun onLoad() { - registerInputs(CacheType.FLUID, getFluidInputLocations()) - } - - override fun onUnload() { - releaseInputs(CacheType.FLUID, getFluidInputLocations()) - } - - override fun handleRemoval() { - releaseInputs(CacheType.FLUID, getFluidInputLocations()) - } + override val inputsData: InputsData = InputsData.builder(this) + .addFluidInput(0, -1, 0) + .build() private val worldConfig get() = world.ion.configuration.gasConfiguration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt index 03feea2f28..849b75c9ca 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/storage/FluidStorageMultiblock.kt @@ -11,7 +11,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidSt import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.UnlimitedInternalStorage import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -60,20 +60,9 @@ abstract class FluidStorageMultiblock(val capacity: Int) : Multiblock(), EntityM SplitFluidDisplay(mainStorage, +0.0, -0.0, +0.0, 0.45f), ).register() - override val fluidInputOffsets: Array = arrayOf(Vec3i(0, -1, 0)) - - override fun onLoad() { - registerInputs(CacheType.FLUID, getFluidInputLocations()) - } - - override fun onUnload() { - releaseInputs(CacheType.FLUID, getFluidInputLocations()) - } - - override fun handleRemoval() { - releaseInputs(CacheType.FLUID, getFluidInputLocations()) - - } + override val inputsData: InputsData = InputsData.builder(this) + .addFluidInput(0, -1, 0) + .build() override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { storeFluidData(store, adapterContext) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt index 09172beb73..a43417ab06 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.SPLITTER_DIRECTION import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -130,6 +131,7 @@ object ItemSplitterMultiblock : Multiblock(), InteractableMultiblock, EntityMult private var isBlacklist: Boolean ) : MultiblockEntity(manager, ItemSplitterMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, LegacyMultiblockEntity { override val tickingManager: TickingManager = TickingManager(interval = 20) + override val inputsData: InputsData = none() override fun tick() { val filterItems = getBlacklist() ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 411ba0b637..b3376a50a0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import org.bukkit.Location import org.bukkit.World @@ -95,6 +96,8 @@ object MobDefender : Multiblock(), EntityMultiblock = arrayOf(Vec3i(0, 0, 0)) override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } + + override val inputsData: InputsData = InputsData.builder(this).addPowerInput(0, 0, 0).build() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 8a1f8d75c4..9d1769b8dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -54,7 +54,12 @@ abstract class TransportCache(val holder: CacheHolder<*>) { cache(location, block) } - fun cache(location: BlockKey, block: Block): Node? { + private val mutex = Any() + + fun cache(location: BlockKey, block: Block): Node? = synchronized(mutex) { + // On race conditions + cache[location]?.let { return@synchronized (it as? CacheState.Present)?.node } + val type = nodeFactory.cache(block) val state = if (type == null) CacheState.Empty else CacheState.Present(type) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt new file mode 100644 index 0000000000..d3db1db172 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt @@ -0,0 +1,61 @@ +package net.horizonsend.ion.server.features.transport.nodes.inputs + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.transport.util.CacheType + +class InputsData private constructor (val holder: MultiblockEntity, private val inputs: List){ + fun registerInputs() { + for (input in inputs) { + input.register(holder.manager.getInputManager(), holder) + } + } + + fun releaseInputs() { + for (input in inputs) { + input.release(holder.manager.getInputManager(), holder) + } + } + + companion object { + fun builder(holder: MultiblockEntity): Builder = Builder(holder) + } + + data class BuiltInputData( + private val type: CacheType, + private val offsetRight: Int, + private val offsetUp: Int, + private val offsetForward: Int, + ) { + private fun getRealPos(holder: MultiblockEntity) = holder.getKeyRelative(offsetRight, offsetUp, offsetForward) + + fun register(manager: InputManager, holder: MultiblockEntity) { + manager.registerInput(type, getRealPos(holder), holder) + } + + fun release(manager: InputManager, holder: MultiblockEntity) { + manager.deRegisterInput(type, getRealPos(holder), holder) + } + } + + class Builder(val holder: MultiblockEntity) { + private val data: MutableList = mutableListOf() + + private fun addInput(type: CacheType, offsetRight: Int, offsetUp: Int, offsetForward: Int): Builder { + data.add(BuiltInputData(type, offsetRight, offsetUp, offsetForward)) + + return this + } + + fun addPowerInput(offsetRight: Int, offsetUp: Int, offsetForward: Int): Builder { + return addInput(CacheType.POWER, offsetRight, offsetUp, offsetForward) + } + + fun addFluidInput(offsetRight: Int, offsetUp: Int, offsetForward: Int): Builder { + return addInput(CacheType.FLUID, offsetRight, offsetUp, offsetForward) + } + + fun build(): InputsData { + return InputsData(holder, data) + } + } +} From 44b73814d1db99cf13e97444b243b99a02aa9f3c Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Dec 2024 18:30:39 -0600 Subject: [PATCH 367/500] don't check chunks if holder is ship --- .../features/custom/items/misc/MultimeterItem.kt | 3 ++- .../transport/manager/holders/CacheHolder.kt | 3 +++ .../manager/holders/ChunkCacheHolder.kt | 6 ++++++ .../transport/manager/holders/ShipCacheHolder.kt | 5 +++++ .../transport/nodes/cache/FluidTransportCache.kt | 2 +- .../transport/nodes/cache/PowerTransportCache.kt | 2 +- .../transport/nodes/cache/TransportCache.kt | 3 ++- .../features/transport/nodes/types/Node.kt | 16 +++++++++++----- .../features/transport/util/NodePathfinding.kt | 12 ++++++++---- 9 files changed, 39 insertions(+), 13 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 458e8c90d2..89f0c5b6ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.transport.util.PathfindingNodeWrapper import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getHeuristic import net.horizonsend.ion.server.features.transport.util.getNeighbors +import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE @@ -149,7 +150,7 @@ object MultimeterItem : CustomItem("MULTIMETER") { queueRemove(current) visited.add(current.node.position) - val neighbors = getNeighbors(current, null) + val neighbors = getNeighbors(current, { cacheType, world, pos -> getOrCacheNode(cacheType, world, pos) },null) if (neighbors.isEmpty()) audience.userError("Empty neighbors") for (newNeighbor in neighbors) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt index 96bafff067..21996ed532 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World @@ -39,4 +40,6 @@ interface CacheHolder { fun getMultiblockManager(): MultiblockManager fun getExtractorManager(): ExtractorManager + + abstract val nodeProvider: (CacheType, World, BlockKey) -> Node? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt index a8a7ec224a..84d9b8c0f3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt @@ -5,6 +5,8 @@ import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManag import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -52,4 +54,8 @@ class ChunkCacheHolder private constructor (override val tran override fun getExtractorManager(): ExtractorManager { return transportManager.extractorManager } + + override val nodeProvider: (CacheType, World, BlockKey) -> Node? = { cacheType, world, pos -> + getOrCacheNode(cacheType, world, pos) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 1a627070da..50feb23109 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.transport.manager.ShipTransportManage import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -63,4 +64,8 @@ class ShipCacheHolder(override val transportManager: ShipTran NewTransport.invalidateCache(getWorld(), x, y, z) } } + + override val nodeProvider: (CacheType, World, BlockKey) -> Node? = { cacheType, world, pos -> + getInternalNode(pos) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 4eed3f8aa7..221f88a42f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -105,7 +105,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa val numDestinations = filteredDestinations.size val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, filteredDestinations[it]) { node, _ -> + getIdealPath(source, filteredDestinations[it], holder.nodeProvider) { node, _ -> (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) ?: true) } }.getOrNull() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 8ff9ff23dc..b7d4961b21 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -120,7 +120,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val numDestinations = filteredDestinations.size val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, filteredDestinations[it]) + getIdealPath(source, filteredDestinations[it], holder.nodeProvider) }.getOrNull() } var maximumResistance: Double = -1.0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 9d1769b8dc..e304cf485b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -167,6 +167,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { world = holder.getWorld(), position = originPos, backwards = BlockFace.SELF, + holder.nodeProvider, null )) @@ -176,7 +177,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { if (current.type is T && check(current)) destinations.add(current.position) - visitQueue.addAll(current.getNextNodes(null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) + visitQueue.addAll(current.getNextNodes(holder.nodeProvider, null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) } return destinations.toList() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt index d04c3d5cbe..5a4af8e96e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.World @@ -23,13 +22,20 @@ interface Node { **/ fun canTransferFrom(other: Node, offset: BlockFace): Boolean - fun getNextNodes(world: World, position: BlockKey, backwards: BlockFace, filter: ((Node, BlockFace) -> Boolean)?): List { + fun getNextNodes( + world: World, + position: BlockKey, + backwards: BlockFace, + cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, + filter: ((Node, BlockFace) -> Boolean)? + ): List { val adjacent = getTransferableDirections(backwards) val nodes = mutableListOf() for (adjacentFace in adjacent) { val pos = getRelative(position, adjacentFace) - val cached = getOrCacheNode(cacheType, world, pos) ?: continue +// val cached = getOrCacheNode(cacheType, world, pos) ?: continue + val cached = cachedNodeProvider.invoke(cacheType, world, pos) ?: continue if (!cached.canTransferFrom(this, adjacentFace) || !canTransferTo(cached, adjacentFace)) continue if (filter != null && !filter.invoke(cached, adjacentFace)) continue @@ -43,8 +49,8 @@ interface Node { fun filterPositionData(nextNodes: List, backwards: BlockFace): List = nextNodes data class NodePositionData(val type: Node, val world: World, val position: BlockKey, val offset: BlockFace) { - fun getNextNodes(filter: ((Node, BlockFace) -> Boolean)?): List = - type.getNextNodes(world, position, offset.oppositeFace, filter) + fun getNextNodes(cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, filter: ((Node, BlockFace) -> Boolean)?): List = + type.getNextNodes(world, position, offset.oppositeFace, cachedNodeProvider, filter) } fun onInvalidate() {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 9214e4370f..8b8c435b2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -21,7 +21,7 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ -fun getIdealPath(from: Node.NodePositionData, to: BlockKey, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): Array? { +fun getIdealPath(from: Node.NodePositionData, to: BlockKey, cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -58,7 +58,7 @@ fun getIdealPath(from: Node.NodePositionData, to: BlockKey, pathfindingFilter: ( queueRemove(current) visited.add(current.node.hashCode()) - for (neighbor in getNeighbors(current, pathfindingFilter)) { + for (neighbor in getNeighbors(current, cachedNodeProvider, pathfindingFilter)) { if (visited.contains(neighbor.node.hashCode())) continue neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) @@ -79,8 +79,12 @@ fun getIdealPath(from: Node.NodePositionData, to: BlockKey, pathfindingFilter: ( } // Wraps neighbor nodes in a data class to store G and F values for pathfinding. Should probably find a better solution -fun getNeighbors(current: PathfindingNodeWrapper, filter: ((Node, BlockFace) -> Boolean)?): Array { - val transferable = current.node.getNextNodes(filter) +fun getNeighbors( + current: PathfindingNodeWrapper, + cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, + filter: ((Node, BlockFace) -> Boolean)? +): Array { + val transferable = current.node.getNextNodes(cachedNodeProvider, filter) return Array(transferable.size) { val next = transferable[it] From 14628120d9bf72616d9d33afb0eadb6f47f8fd2b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 4 Dec 2024 23:31:23 -0600 Subject: [PATCH 368/500] fix display rotation --- .../client/display/modular/DisplayHandlers.kt | 36 +++++--------- .../display/modular/TextDisplayHandler.kt | 45 ++++++++++------- .../client/display/modular/display/Display.kt | 48 +++++++++++-------- .../modular/display/FlowMeterDisplay.kt | 22 ++------- .../display/fluid/SimpleFluidDisplay.kt | 9 ++++ .../multiblock/manager/MultiblockManager.kt | 1 + .../manager/ShipMultiblockManager.kt | 7 +-- .../type/fluid/ElectrolysisMultiblock.kt | 10 +++- .../starship/movement/StarshipMovement.kt | 1 + .../manager/holders/ShipCacheHolder.kt | 2 +- 10 files changed, 95 insertions(+), 86 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index 07b4fb15ed..acbccdaa41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -5,11 +5,6 @@ import net.horizonsend.ion.server.features.client.display.modular.display.Displa import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -23,37 +18,32 @@ object DisplayHandlers : IonServerComponent() { fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg display: Display): TextDisplayHandler { val signDirection = entity.structureDirection.oppositeFace + val signLocation = entity.getSignLocation() return TextDisplayHandler( entity, entity.world, - entity.x.toDouble() + 0.5, - entity.y.toDouble() + 0.4, - entity.z.toDouble() + 0.5, - offsetRight = 0.0, - offsetUp = 0.0, - offsetForward = 0.61, + signLocation.blockX, + signLocation.blockY, + signLocation.blockZ, + 0.0, + -0.1, + -0.39, // Back up towards the sign signDirection, *display ) } fun newBlockOverlay(holder: DisplayHandlerHolder, world: World, block: Vec3i, direction: BlockFace, vararg display: Display): TextDisplayHandler { - val facingBlock = getRelative(toBlockKey(block), direction) - - val x = getX(facingBlock).toDouble() + 0.5 - val y = getY(facingBlock).toDouble() + 0.35 - val z = getZ(facingBlock).toDouble() + 0.5 - return TextDisplayHandler( holder, world, - x, - y, - z, - offsetRight = 0.0, - offsetUp = 0.0, - offsetForward = -0.45, + block.x, + block.y, + block.z, + 0.0, + -0.15, + 0.55, direction, *display ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index 46a46edc1d..dab3dc65e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.client.display.modular import net.horizonsend.ion.server.features.client.display.modular.display.Display import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.starship.movement.TranslateMovement import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Axis @@ -13,12 +12,15 @@ import org.bukkit.block.BlockFace class TextDisplayHandler( val holder: DisplayHandlerHolder, var world: World, - var anchorX: Double, - var anchorY: Double, - var anchorZ: Double, - var offsetRight: Double, - var offsetUp: Double, - var offsetForward: Double, + + var blockX: Int, + var blockY: Int, + var blockZ: Int, + + val offsetRight: Double, + val offsetUp: Double, + val offsetForward: Double, + var facing: BlockFace, vararg display: Display ) { @@ -56,24 +58,33 @@ class TextDisplayHandler( } fun getLocation(): Location { - val rightFace = if (facing.axis == Axis.Y) BlockFace.NORTH else facing.rightFace + val forwardFace = facing + val rightFace = if (forwardFace.axis == Axis.Y) BlockFace.NORTH else forwardFace.rightFace - val offsetX = (rightFace.modX * offsetRight) + (facing.modX * offsetForward) - val offsetY = offsetUp - val offsetZ = (rightFace.modZ * offsetRight) + (facing.modZ * offsetForward) + // Start from a center location, should be the same for every block + val centerLocation = Location(world, blockX + 0.5, blockY + 0.5, blockZ + 0.5) - return Location(world, anchorX + offsetX, anchorY + offsetY, anchorZ + offsetZ) + // Offset from the center location + centerLocation.add( + rightFace.modX * offsetRight + forwardFace.modX * offsetForward, + offsetUp, + rightFace.modZ * offsetRight + forwardFace.modZ * offsetForward + ) + + return centerLocation } fun displace(movement: StarshipMovement) { val oldFace = facing facing = movement.displaceFace(oldFace) - if (movement is TranslateMovement) { - anchorX += movement.dx - anchorY += movement.dy - anchorZ += movement.dz - } + val newX = movement.displaceX(blockX, blockZ) + val newY = movement.displaceY(blockY) + val newZ = movement.displaceZ(blockZ, blockX) + + blockX = newX + blockY = newY + blockZ = newZ for (display in displays) { display.resetPosition(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index 4c472797a1..36b0a21af3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -18,6 +18,7 @@ import net.minecraft.world.entity.EntityType import org.bukkit.Axis.Y import org.bukkit.Bukkit.getPlayer import org.bukkit.Color +import org.bukkit.Location import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.v1_20_R3.CraftServer import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay @@ -32,7 +33,7 @@ abstract class Display( private val offsetForward: Double, val scale: Float ) { - var shownPlayers = mutableSetOf() + private var shownPlayers = mutableSetOf() protected lateinit var handler: TextDisplayHandler lateinit var entity: TextDisplay; private set @@ -60,6 +61,23 @@ abstract class Display( val mutex = Any() + fun getLocation(parent: TextDisplayHandler): Location { + val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace + + val offsetX = (rightFace.modX * offsetRight) + (parent.facing.modX * offsetForward) + val offsetY = offsetUp + val offsetZ = (rightFace.modZ * offsetRight) + (parent.facing.modZ * offsetForward) + + val parentLoc = parent.getLocation() + + return Location( + parent.world, + parentLoc.x + offsetX, + parentLoc.y + offsetY, + parentLoc.z + offsetZ + ) + } + fun initialize(parent: TextDisplayHandler) = synchronized(mutex) { if (isInitializing || this::handler.isInitialized) { return@synchronized @@ -69,36 +87,24 @@ abstract class Display( this.handler = parent - val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace - - val offsetX = rightFace.modX * offsetRight + parent.facing.modX * offsetForward - val offsetY = offsetUp - val offsetZ = rightFace.modZ * offsetRight + parent.facing.modZ * offsetForward - - val parentLoc = parent.getLocation() + val location = getLocation(parent) runCatching { entity = createEntity(parent).getNMSData( - parentLoc.x + offsetX, - parentLoc.y + offsetY, - parentLoc.z + offsetZ + location.x, + location.y, + location.z ) } } fun resetPosition(parent: TextDisplayHandler) { - val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace - - val offsetX = (rightFace.modX * offsetRight) + (parent.facing.modX * offsetForward) - val offsetY = offsetUp - val offsetZ = (rightFace.modZ * offsetRight) + (parent.facing.modZ * offsetForward) - - val parentLoc = parent.getLocation() + val location = getLocation(parent) entity.teleportTo( - parentLoc.x + offsetX, - parentLoc.y + offsetY, - parentLoc.z + offsetZ + location.x, + location.y, + location.z ) entity.setTransformation(com.mojang.math.Transformation( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index 4f0abdceed..7172cd88f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -13,11 +13,11 @@ import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay class FlowMeterDisplay( private val meter: PowerNode.PowerFlowMeter, - offsetLeft: Double, + offsetRight: Double, offsetUp: Double, - offsetBack: Double, + offsetForward: Double, scale: Float -): Display(offsetLeft, offsetUp, offsetBack, scale) { +): Display(offsetRight, offsetUp, offsetForward, scale) { override fun register() {} override fun deRegister() {} @@ -36,20 +36,4 @@ class FlowMeterDisplay( println("Create entity $this") return super.createEntity(parent) } - - @Synchronized - override fun display() { - println("Display") - super.display() - } - - override fun remove() { - println("Remove") - super.remove() - } - - override fun update() { - println("Update") - super.update() - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index 13a9e5b4f3..688795d043 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -1,12 +1,14 @@ package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay class SimpleFluidDisplay( storage: StorageContainer, @@ -22,4 +24,11 @@ class SimpleFluidDisplay( companion object { val empty = text("Empty", NamedTextColor.GRAY, TextDecoration.ITALIC) } + + override fun createEntity(parent: TextDisplayHandler): CraftTextDisplay { + Throwable().printStackTrace() + + println("Create entity $this") + return super.createEntity(parent) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 1a21cf937c..1e498fbf0b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -60,6 +60,7 @@ abstract class MultiblockManager(val log: Logger) { } } + multiblockEntities.remove(entity.locationKey)?.processRemoval() multiblockEntities[entity.locationKey] = entity entity.processLoad() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 5fa0b37d4d..ffcd35ea05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -166,18 +166,19 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe /** Mostly to be used with blueprint load or loadship, loads entities from their sign data */ private fun tryFixEntities() { starship.iterateBlocks { x, y, z -> - if (isOccupied(x, y, z)) return@iterateBlocks - val type = getBlockTypeSafe(world, x, y, z) if (type?.isWallSign != true) return@iterateBlocks val state = world.getBlockState(x, y, z) as? Sign ?: return@iterateBlocks + val origin = MultiblockEntity.getOriginFromSign(state) + + if (isOccupied(origin.x, origin.y, origin.z)) return@iterateBlocks + val multiblock = MultiblockAccess.getFast(state) if (multiblock !is EntityMultiblock<*>) return@iterateBlocks val data = state.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return MultiblockEntities.migrateFromSign(state, multiblock) - val origin = MultiblockEntity.getOriginFromSign(state) // In case it moved data.x = origin.x diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 194b2f4c3d..8291ab6bfb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -187,8 +187,14 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock + player.information("Display $display") + player.information("Offset ${display.getLocation(handler)}") + player.highlightBlock(display.entity.blockPosition().toVec3i(), 10L) } player.information(entity.toString()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt index cf71b2f287..dd4438d7bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/movement/StarshipMovement.kt @@ -139,6 +139,7 @@ abstract class StarshipMovement(val starship: ActiveStarship, val newWorld: Worl updateCenter() updateSubsystems(world2) starship.multiblockManager.displace(this) + starship.transportManager.displace(this) onComplete() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 50feb23109..615c9e2c36 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -65,7 +65,7 @@ class ShipCacheHolder(override val transportManager: ShipTran } } - override val nodeProvider: (CacheType, World, BlockKey) -> Node? = { cacheType, world, pos -> + override val nodeProvider: (CacheType, World, BlockKey) -> Node? = { _, _, pos -> getInternalNode(pos) } } From 646f316a24f0fc425daeaf3da05af53d15eb0f7a Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 5 Dec 2024 00:15:12 -0600 Subject: [PATCH 369/500] reformat debug commands, fix node displacement --- .../server/command/admin/IonChunkCommand.kt | 145 ----------------- .../server/command/misc/MultiblockCommand.kt | 81 ++++++++++ .../command/misc/TransportDebugCommand.kt | 147 ++++++++++++++++-- .../transport/manager/ShipTransportManager.kt | 2 +- .../transport/nodes/cache/TransportCache.kt | 5 +- 5 files changed, 220 insertions(+), 160 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt index d97b0bb187..3d27418819 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/IonChunkCommand.kt @@ -1,163 +1,18 @@ package net.horizonsend.ion.server.command.admin import co.aikar.commands.annotation.CommandAlias -import co.aikar.commands.annotation.CommandCompletion -import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks -import net.horizonsend.ion.server.features.transport.nodes.types.Node -import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode -import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.kyori.adventure.text.Component.text import org.bukkit.entity.Player @CommandAlias("ionchunk") object IonChunkCommand : SLCommand() { - @Subcommand("dumpEntities") - fun onDumpEntities(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { - val manager = sender.chunk.ion().multiblockManager - val entities = manager.getAllMultiblockEntities().toList() - - sender.sendMessage(formatPaginatedMenu( - entities.size, - "/ionchunk dumpentities ${visual ?: false}", - page ?: 1, - ) { index -> - val (key, entity) = entities[index] - - val vec = toVec3i(key) - - text("$vec : $entity") - }) - - if (visual == true) { - for ((key, _) in entities) { - val vec = toVec3i(key) - - sender.highlightBlock(vec, 30L) - } - } - - sender.information("Sync Ticked: ${manager.syncTickingMultiblockEntities}") - sender.information("Async Ticked: ${manager.asyncTickingMultiblockEntities}") - } - - @Subcommand("remove all") - fun onRemoveAll(sender: Player) { - val ionChunk = sender.chunk.ion() - val entities = ionChunk.multiblockManager.getAllMultiblockEntities() - - for ((key, _) in entities) { - val (x, y, z) = toVec3i(key) - - ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) - } - } - - @Subcommand("dump nodes") - @CommandCompletion("power") /* |item|gas") */ - fun dumpNodes(sender: Player, network: CacheType) { - val ionChunk = sender.chunk.ion() - val grid = network.get(ionChunk) - - sender.information("${grid.getRawCache().size} covered position(s).") - sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") - - grid.getRawCache().forEach { (t, _) -> - val vec = toVec3i(t) - sender.highlightBlock(vec, 50L) - } - } - - @Subcommand("dump extractors") - fun dumpExtractors(sender: Player, network: CacheType) { - val ionChunk = sender.chunk.ion() - val extractors = network.get(ionChunk).holder.getExtractorManager() - - sender.information("${extractors.getExtractors().size} covered position(s).") - - extractors.getExtractors().forEach { extractor -> - sender.highlightBlock(toVec3i(extractor.pos), 50L) - } - } - - @Subcommand("dump") - @CommandCompletion("power") - fun dumpNetwork(sender: Player, network: CacheType) { - val ionChunk = sender.chunk.ion() - val grid = network.get(ionChunk) - - sender.information("${grid.getRawCache().size} covered position(s).") - sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") - - when (grid) { -// is PowerNodeManager -> { -// sender.information("${grid.solarPanels.size} solar panels") -// sender.information("${grid.extractors.size} extractors") -// sender.information("Node list: ${grid.nodes.values.groupBy { it.javaClass.simpleName }.mapValues { it.value.size }.entries.joinToString { it.toString() + "\n" }}") -// } - } - } - @Subcommand("dumpchunk") fun dumpChunk(sender: Player) { val ionChunk = sender.chunk.ion() sender.information("Chunk: $ionChunk") } - - @Subcommand("get node key") - fun getNode(sender: Player, key: Long, network: CacheType) { - val ionChunk = sender.chunk.ion() - val grid = network.get(ionChunk) - - sender.information("Targeted node: ${grid.getRawCache()[key]}") - } - - @Subcommand("get node look") - fun getNode(sender: Player, network: CacheType) { - val (node, location) = requireLookingAt(sender, network) - sender.information("Targeted node: $node at ${toVec3i(location)}") - } - - @Subcommand("test extractor") - fun onTick(sender: Player, type: CacheType) { - val (node, location) = requireLookingAt(sender, type) - val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } - val grid = type.get(chunk) - if (grid.holder.getExtractorManager().isExtractor(location)) fail { "Extractor not targeted" } - - grid.tickExtractor(location, 1.0) - } - - @Subcommand("test flood") - fun onTestFloodFill(sender: Player, network: CacheType) { - sender.information("Trying to find input nodes") - val (_, location) = requireLookingAt(sender, network) - val cache = network.get(sender.chunk.ion()) - val destinations = cache.getNetworkDestinations(location) { true } - sender.information("${destinations.size} destinations") - sender.highlightBlocks(destinations.map(::toVec3i), 50L) - } - - private fun requireLookingAt(sender: Player, network: CacheType): Pair { - val targeted = sender.getTargetBlock(null, 10) - val ionChunk = targeted.chunk.ion() - val grid = network.get(ionChunk) - val key = toBlockKey(targeted.x, targeted.y, targeted.z) - - val node = grid.getOrCache(key) ?: fail { "You aren't looking at a node!" } - return node to key - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index 1eff700689..f9ff6bd1c5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -6,22 +6,28 @@ import co.aikar.commands.PaperCommandManager import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission +import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.bracketed +import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.displayBlock +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.features.custom.items.misc.MultiblockToken import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration +import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration @@ -154,4 +160,79 @@ object MultiblockCommand : SLCommand() { destination.inventory.addItem(MultiblockToken.constructFor(prePackagedType)) sender.information("Added to inventory") } + + @Subcommand("debug dump entities chunk") + @CommandCompletion("true|false") + fun onDumpEntitiesChunk(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { + val manager = sender.chunk.ion().multiblockManager + val entities = manager.getAllMultiblockEntities().toList() + + sender.sendMessage( + formatPaginatedMenu( + entities.size, + "/ionchunk dumpentities ${visual ?: false}", + page ?: 1, + ) { index -> + val (key, entity) = entities[index] + + val vec = toVec3i(key) + + text("$vec : $entity") + }) + + if (visual == true) { + for ((key, _) in entities) { + val vec = toVec3i(key) + + sender.highlightBlock(vec, 30L) + } + } + + sender.information("Sync Ticked: ${manager.syncTickingMultiblockEntities}") + sender.information("Async Ticked: ${manager.asyncTickingMultiblockEntities}") + } + + @Subcommand("debug dump entities ship") + @CommandCompletion("true|false") + fun onDumpEntitiesShip(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { + val ship = getStarshipPiloting(sender) + val manager = ship.multiblockManager + val entities = manager.getAllMultiblockEntities().toList() + + sender.sendMessage( + formatPaginatedMenu( + entities.size, + "/ionchunk dumpentities ${visual ?: false}", + page ?: 1, + ) { index -> + val (key, entity) = entities[index] + + val vec = toVec3i(key) + + text("$vec : $entity") + }) + + if (visual == true) { + for ((key, _) in entities) { + val vec = toVec3i(key) + + sender.highlightBlock(vec, 30L) + } + } + + sender.information("Sync Ticked: ${manager.syncTickingMultiblockEntities}") + sender.information("Async Ticked: ${manager.asyncTickingMultiblockEntities}") + } + + @Subcommand("debug remove all entities") + fun onRemoveAll(sender: Player) { + val ionChunk = sender.chunk.ion() + val entities = ionChunk.multiblockManager.getAllMultiblockEntities() + + for ((key, _) in entities) { + val (x, y, z) = toVec3i(key) + + ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 541f47342f..c984728c7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -1,17 +1,31 @@ package net.horizonsend.ion.server.command.misc import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import io.papermc.paper.util.StacktraceDeobfuscator +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand +import net.horizonsend.ion.server.command.admin.IonChunkCommand +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import org.bukkit.block.Block import org.bukkit.command.CommandSender import org.bukkit.entity.Player import org.slf4j.Logger @@ -28,18 +42,7 @@ object TransportDebugCommand : SLCommand() { sender.success("Reloaded config") } - @Subcommand("dump inputs") - fun dumpInputs(sender: Player, type: CacheType) { - val inputManager = sender.world.ion.inputManager - val loc = Vec3i(sender.location) - val inputs = inputManager.getLocations(type) - .map { toVec3i(it) } - .filter { it.distance(loc) < 100.0 } - - sender.highlightBlocks(inputs, 50L) - } - - @Subcommand("force dump") + @Subcommand("threaddump") fun forceDump(sender: Player) { log.error("Entire Thread Dump:") val threads = ManagementFactory.getThreadMXBean().dumpAllThreads(true, true) @@ -71,4 +74,124 @@ object TransportDebugCommand : SLCommand() { log.error("\t\t" + stack) } } + + @Subcommand("dump inputs chunk") + fun dumpInputsChunk(sender: Player, type: CacheType) { + val inputManager = sender.world.ion.inputManager + val loc = Vec3i(sender.location) + val inputs = inputManager.getLocations(type) + .map { toVec3i(it) } + .filter { it.distance(loc) < 100.0 } + + sender.highlightBlocks(inputs, 50L) + sender.information("${inputs.size} inputs") + } + + @Subcommand("dump inputs starship") + fun dumpInputsShip(sender: Player, type: CacheType) { + val ship = getStarshipRiding(sender) + val inputManager = ship.transportManager.inputManager + val loc = Vec3i(sender.location) + val inputs = inputManager.getLocations(type) + .map { toVec3i(it) } + .filter { it.distance(loc) < 100.0 } + + sender.highlightBlocks(inputs, 50L) + sender.information("${inputs.size} inputs") + } + + @Subcommand("dump nodes chunk") + @CommandCompletion("power") /* |item|gas") */ + fun dumpNodesChunk(sender: Player, network: CacheType) { + val ionChunk = sender.chunk.ion() + val grid = network.get(ionChunk) + + sender.information("${grid.getRawCache().size} covered position(s).") + sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") + + grid.getRawCache().forEach { (t, _) -> + val vec = toVec3i(t) + sender.highlightBlock(vec, 50L) + } + } + + @Subcommand("dump nodes ship") + @CommandCompletion("power") /* |item|gas") */ + fun dumpNodesShip(sender: Player, network: CacheType) { + val ship = getStarshipRiding(sender) + val grid = network.get(ship) + + sender.information("${grid.getRawCache().size} covered position(s).") + sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") + + grid.getRawCache().forEach { (t, _) -> + val vec = toVec3i(t) + sender.highlightBlock(vec, 50L) + } + } + + @Subcommand("dump extractors chunk") + fun dumpExtractorsChunk(sender: Player, network: CacheType) { + val ionChunk = sender.chunk.ion() + val extractors = network.get(ionChunk).holder.getExtractorManager() + + sender.information("${extractors.getExtractors().size} covered position(s).") + + extractors.getExtractors().forEach { extractor -> + sender.highlightBlock(toVec3i(extractor.pos), 50L) + } + } + + @Subcommand("dump extractors ship") + fun dumpExtractorsShip(sender: Player, network: CacheType) { + val ship = getStarshipRiding(sender) + val extractors = network.get(ship).holder.getExtractorManager() + + sender.information("${extractors.getExtractors().size} covered position(s).") + + extractors.getExtractors().forEach { extractor -> + sender.highlightBlock(toVec3i(extractor.pos), 50L) + } + } + + private fun requireLookingAt(sender: Player, network: (Block) -> TransportCache): Pair { + val targeted = sender.getTargetBlock(null, 10) + val grid = network(targeted) + val key = toBlockKey(targeted.x, targeted.y, targeted.z) + + val node = grid.getOrCache(key) ?: fail { "You aren't looking at a node!" } + return node to key + } + + @Subcommand("get node look chunk") + fun getNodeChunk(sender: Player, network: CacheType) { + val (node, location) = requireLookingAt(sender) { network.get(it.chunk.ion()) } + sender.information("Targeted node: $node at ${toVec3i(location)}") + } + + @Subcommand("get node look ship") + fun getNodeShip(sender: Player, network: CacheType) { + val (node, location) = requireLookingAt(sender) { network.get(getStarshipRiding(sender)) } + sender.information("Targeted node: $node at ${toVec3i(location)}") + } + + @Subcommand("test extractor test") + fun onTick(sender: Player, type: CacheType) { + val (node, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } + val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } + val grid = type.get(chunk) + if (grid.holder.getExtractorManager().isExtractor(location)) IonChunkCommand.fail { "Extractor not targeted" } + + grid.tickExtractor(location, 1.0) + } + + @Subcommand("test flood test") + fun onTestFloodFill(sender: Player, type: CacheType) { + sender.information("Trying to find input nodes") + val (_, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } + val cache = type.get(sender.chunk.ion()) + val destinations = cache.getNetworkDestinations(location) { true } + sender.information("${destinations.size} destinations") + sender.highlightBlocks(destinations.map(::toVec3i), 50L) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 1dd388f5e1..52be92596b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.features.transport.nodes.inputs.ShipInputManag class ShipTransportManager(val starship: Starship) : TransportManager() { override val extractorManager: ShipExtractorManager = ShipExtractorManager(starship) - private val inputManager = ShipInputManager(this) + val inputManager = ShipInputManager(this) override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } override val solarPanelManager: ShipCacheHolder = ShipCacheHolder(this) { SolarPanelCache(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index e304cf485b..9198bc8c39 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -80,9 +80,10 @@ abstract class TransportCache(val holder: CacheHolder<*>) { fun displace(movement: StarshipMovement) { val new = ConcurrentHashMap() - for ((key, cached) in new) { + for ((key, cached) in cache) { val newKey = movement.displaceKey(key) - if (cached is ComplexNode) cached.displace(movement) + val presentNode = (cached as? CacheState.Present)?.node + if (presentNode is ComplexNode) presentNode.displace(movement) new[newKey] = cached } From a2de769bb23d3ad7d08f92a7dc69e57bbff5ccbc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Fri, 20 Dec 2024 14:14:49 -0600 Subject: [PATCH 370/500] fix upstream :( --- .../server/command/admin/ItemDebugCommand.kt | 8 +-- .../server/command/nations/NationCommand.kt | 18 +------ .../nations/admin/NationAdminCommand.kt | 2 +- .../ion/server/command/space/PlanetCommand.kt | 4 +- .../command/starship/MiscStarshipCommands.kt | 6 +-- .../configuration/ConfigurationFiles.kt | 3 ++ .../ion/server/configuration/util/Pos.kt | 2 +- .../ion/server/data/migrator/DataMigrators.kt | 4 +- .../ion/server/data/migrator/DataVersion.kt | 2 +- .../modern/aspect/ChangeIdentifierMigrator.kt | 2 +- .../item/modern/migrator/AspectMigrator.kt | 2 +- .../item/modern/migrator/IdentifierUpdate.kt | 2 +- .../display/modular/MultiBlockDisplay.kt | 2 +- .../client/display/modular/display/Display.kt | 25 ++++------ .../modular/display/FlowMeterDisplay.kt | 2 +- .../display/fluid/SimpleFluidDisplay.kt | 2 +- .../features/custom/blocks/CustomBlocks.kt | 40 +++++++-------- .../custom/blocks/InteractableCustomBlock.kt | 2 +- .../custom/blocks/MultiblockWorkbench.kt | 34 ++++++------- .../features/custom/items/CustomItem.kt | 2 +- .../custom/items/CustomItemRegistry.kt | 22 +++++++- .../custom/items/component/GasStorage.kt | 2 +- .../custom/items/component/ModManager.kt | 2 +- .../custom/items/misc/MultiblockToken.kt | 46 ++++++++--------- .../custom/items/misc/MultimeterItem.kt | 27 +++++----- .../custom/items/misc/PackagedMultiblock.kt | 33 ++++++------ .../custom/items/misc/TransportFilterItem.kt | 13 +++-- .../features/custom/items/misc/Wrench.kt | 36 +++++++------ .../custom/items/type/ProgressHolder.kt | 2 +- .../custom/items/type/armor/PowerArmorItem.kt | 2 +- .../custom/items/type/tool/Battery.kt | 27 +++++++--- .../custom/items/type/tool/PowerChainsaw.kt | 2 +- .../custom/items/type/tool/PowerDrill.kt | 2 +- .../custom/items/type/tool/PowerHoe.kt | 2 +- .../items/type/tool/mods/ToolModMenu.kt | 2 +- .../items/type/weapon/sword/EnergySword.kt | 2 +- .../features/custom/items/util/ItemFactory.kt | 2 +- .../ion/server/features/gui/GuiItems.kt | 2 +- .../ion/server/features/machine/CryoPods.kt | 2 +- .../multiblock/crafting/MultiblockRecipes.kt | 50 +++++++++---------- .../crafting/ingredient/Consumable.kt | 4 +- .../crafting/ingredient/ItemIngredient.kt | 2 +- .../ticked/TickedMultiblockEntityParent.kt | 6 +-- .../manager/ChunkMultiblockManager.kt | 2 +- .../multiblock/shape/MultiblockShape.kt | 4 +- .../type/ammo/AmmoPressMultiblock.kt | 3 +- .../type/autocrafter/AutoCrafterMultiblock.kt | 1 + .../type/fluid/CanisterVentMultiblock.kt | 8 +-- .../CanisterGasCollectorMultiblock.kt | 17 ++++--- .../type/power/charger/ChargerMultiblock.kt | 9 +--- .../powerfurnace/PowerFurnaceMultiblock.kt | 31 ++++++++---- .../weapon/turret/TurretBaseMultiblock.kt | 8 +-- .../multiblock/util/asyncTileEntities.kt | 14 +++--- .../region/types/RegionSolarSiegeZone.kt | 2 +- .../features/nations/sieges/SolarSiege.kt | 2 +- .../features/nations/sieges/SolarSieges.kt | 2 +- .../progression/achievements/Achievement.kt | 2 +- .../ion/server/features/space/Space.kt | 3 +- .../server/features/space/body/CachedMoon.kt | 2 +- .../space/body/OrbitingCelestialBody.kt | 2 +- .../space/body/planet/CachedOrbitingPlanet.kt | 2 +- .../space/body/planet/CachedPlanet.kt | 4 +- .../space/body/planet/CachedRoguePlanet.kt | 2 +- .../features/starship/StarshipComputers.kt | 2 +- .../starship/active/SubsystemDetector.kt | 2 +- .../player/ActivePlayerController.kt | 2 +- .../control/input/DirecterControlHandler.kt | 4 +- .../control/input/ShiftFlightHandler.kt | 2 +- .../weapon/secondary/CustomTurretSubsystem.kt | 6 +-- .../server/features/transport/NewTransport.kt | 4 +- .../transport/filters/FilterAccess.kt | 2 +- .../transport/filters/FilterBlocks.kt | 4 +- .../manager/extractors/ExtractorManager.kt | 4 +- .../nodes/cache/FluidTransportCache.kt | 6 +-- .../nodes/cache/PowerTransportCache.kt | 10 ++-- .../nodes/cache/solarpanel/SolarPanelCache.kt | 4 +- .../features/transport/util/IonChangeSet.kt | 21 ++++++-- .../server/features/world/chunk/IonChunk.kt | 2 +- .../server/listener/misc/BatteryListener.kt | 47 ----------------- .../listener/misc/ProtectionListener.kt | 6 +-- .../miscellaneous/registrations/Crafting.kt | 7 +-- .../miscellaneous/registrations/Listeners.kt | 10 ++-- .../ion/server/miscellaneous/utils/Items.kt | 2 +- 83 files changed, 357 insertions(+), 364 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BatteryListener.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt index 5070798dde..ef4144ed19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/ItemDebugCommand.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.command.admin import co.aikar.commands.InvalidCommandArgument import co.aikar.commands.PaperCommandManager import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.information @@ -11,14 +12,15 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes.Companion.MOD_MANAGER import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes.Companion.POWER_STORAGE +import net.horizonsend.ion.server.features.custom.items.misc.MultiblockToken import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModRegistry import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModification import net.horizonsend.ion.server.features.custom.items.util.serialization.CustomItemSerialization import net.horizonsend.ion.server.features.gui.GuiItems -import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.features.multiblock.Multiblock -import org.bukkit.command.CommandSender +import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import org.bukkit.Material +import org.bukkit.command.CommandSender import org.bukkit.entity.Player import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.InventoryClickEvent @@ -100,7 +102,7 @@ object ItemDebugCommand : SLCommand() { fun onGivePrepackaged(sender: CommandSender, prePackagedType: Multiblock, recipient: Player?) { val destination: Player = recipient ?: (sender as? Player ?: fail { "You must specify a player!" }) - destination.inventory.addItem(PackagedMultiblockItem.constructFor(prePackagedType)) + destination.inventory.addItem(MultiblockToken.constructFor(prePackagedType)) sender.information("Added to inventory") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt index a2772346fd..6ce111b567 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/NationCommand.kt @@ -40,11 +40,10 @@ import net.horizonsend.ion.server.features.nations.utils.isSemiActive import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.features.progression.achievements.Achievement import net.horizonsend.ion.server.features.progression.achievements.rewardAchievement -import net.horizonsend.ion.server.miscellaneous.utils.Discord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.VAULT_ECO import net.horizonsend.ion.server.miscellaneous.utils.actualStyle -import net.horizonsend.ion.server.miscellaneous.utils.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text @@ -63,21 +62,6 @@ import org.litote.kmongo.EMPTY_BSON import org.litote.kmongo.eq import org.litote.kmongo.ne import java.util.Date -import kotlin.collections.List -import kotlin.collections.Map -import kotlin.collections.any -import kotlin.collections.associate -import kotlin.collections.associateWith -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.count -import kotlin.collections.filter -import kotlin.collections.firstOrNull -import kotlin.collections.map -import kotlin.collections.mapValues -import kotlin.collections.mutableListOf -import kotlin.collections.sortedByDescending -import kotlin.collections.toList import kotlin.math.roundToInt @CommandAlias("nation|n") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/admin/NationAdminCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/admin/NationAdminCommand.kt index 9ca2565bfd..c6a68615c9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/admin/NationAdminCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/nations/admin/NationAdminCommand.kt @@ -29,6 +29,7 @@ import net.horizonsend.ion.common.utils.text.colors.HEColorScheme import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.configuration.ConfigurationFiles +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.nations.NATIONS_BALANCE import net.horizonsend.ion.server.features.nations.NationsBalancing import net.horizonsend.ion.server.features.nations.NationsMap @@ -41,7 +42,6 @@ import net.horizonsend.ion.server.features.nations.sieges.SolarSieges import net.horizonsend.ion.server.features.nations.utils.isActive import net.horizonsend.ion.server.features.nations.utils.isInactive import net.horizonsend.ion.server.features.space.spacestations.CachedSpaceStation -import net.horizonsend.ion.server.miscellaneous.utils.Discord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.kyori.adventure.text.Component import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/space/PlanetCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/space/PlanetCommand.kt index 0fb0632241..61137607d1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/space/PlanetCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/space/PlanetCommand.kt @@ -26,13 +26,13 @@ import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet import net.horizonsend.ion.server.features.space.body.planet.CachedRoguePlanet import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.orNull import org.bukkit.Material import org.bukkit.World import org.bukkit.command.CommandSender import org.bukkit.entity.Player -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit import kotlin.system.measureNanoTime diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt index 6df5d0efcc..fa0bc293d4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/MiscStarshipCommands.kt @@ -66,9 +66,9 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.distance -import net.horizonsend.ion.server.miscellaneous.utils.normalize +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.normalize import net.horizonsend.ion.server.miscellaneous.utils.parseData import net.horizonsend.ion.server.miscellaneous.utils.uploadAsync import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ConfigurationFiles.kt b/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ConfigurationFiles.kt index dc7f61f448..9c8a8da6d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ConfigurationFiles.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/configuration/ConfigurationFiles.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.configuration import net.horizonsend.ion.common.utils.discord.DiscordConfiguration import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.ai.configuration.AISpawningConfiguration +import net.horizonsend.ion.server.features.transport.TransportConfiguration import net.horizonsend.ion.server.miscellaneous.LegacyConfig import java.io.File @@ -32,6 +33,8 @@ object ConfigurationFiles { val nationConfiguration = defineConfigurationFile(configurationFolder, "nation") + val transportSettings = defineConfigurationFile(configurationFolder, "transport") + private inline fun defineConfigurationFile(directory: File, fileName: String): ConfigurationFile { val new = ConfigurationFile(T::class, directory, fileName) return new diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/configuration/util/Pos.kt b/server/src/main/kotlin/net/horizonsend/ion/server/configuration/util/Pos.kt index 3346a905bf..9ad02dd0c0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/configuration/util/Pos.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/configuration/util/Pos.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.configuration.util import kotlinx.serialization.Serializable -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataMigrators.kt b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataMigrators.kt index 3488ff0238..b5e2ad088d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataMigrators.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataMigrators.kt @@ -10,9 +10,9 @@ import net.horizonsend.ion.server.data.migrator.types.item.modern.migrator.Legac import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes.Companion.MOD_MANAGER -import net.horizonsend.ion.server.features.transport.pipe.Pipes -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.registrations.legacy.LegacyPowerArmorModule +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.Chunk import org.bukkit.Material import org.bukkit.entity.Player diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataVersion.kt b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataVersion.kt index 2f92ca4a8a..2685f9ba76 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataVersion.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/DataVersion.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.data.migrator.types.DataMigrator import net.horizonsend.ion.server.data.migrator.types.item.ItemMigrationContext import net.horizonsend.ion.server.data.migrator.types.item.legacy.LegacyCustomItemMigrator import net.horizonsend.ion.server.data.migrator.types.item.modern.migrator.CustomItemStackMigrator -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/aspect/ChangeIdentifierMigrator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/aspect/ChangeIdentifierMigrator.kt index 3b197959b3..af31102f52 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/aspect/ChangeIdentifierMigrator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/aspect/ChangeIdentifierMigrator.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.data.migrator.types.item.modern.aspect import net.horizonsend.ion.server.data.migrator.types.item.MigratorResult -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/AspectMigrator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/AspectMigrator.kt index b59ba97aff..86809d247a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/AspectMigrator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/AspectMigrator.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.data.migrator.types.item.modern.aspect.PullMod import net.horizonsend.ion.server.data.migrator.types.item.modern.aspect.SetLoreMigrator import net.horizonsend.ion.server.data.migrator.types.item.predicate.ItemMigratorPredicate import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.HORIZONSEND_NAMESPACE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.HORIZONSEND_NAMESPACE import net.kyori.adventure.key.Key import net.kyori.adventure.text.Component import org.bukkit.Material diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/IdentifierUpdate.kt b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/IdentifierUpdate.kt index 4911a285e2..f231c14b81 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/IdentifierUpdate.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/data/migrator/types/item/modern/migrator/IdentifierUpdate.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.data.migrator.types.item.modern.migrator import net.horizonsend.ion.server.data.migrator.types.item.MigratorResult import net.horizonsend.ion.server.data.migrator.types.item.predicate.CustomItemPredicate -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/MultiBlockDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/MultiBlockDisplay.kt index e5063fa46c..d0d386fd47 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/MultiBlockDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/MultiBlockDisplay.kt @@ -4,7 +4,7 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter import com.sk89q.worldedit.extent.clipboard.Clipboard import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.World import org.bukkit.block.data.BlockData import org.bukkit.block.data.type.Observer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt index 36b0a21af3..ddf521daa8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.client.display.modular.display import io.papermc.paper.adventure.PaperAdventure import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.moveDisplayEntityPacket import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.miscellaneous.utils.axis @@ -11,7 +12,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket -import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Display.TextDisplay import net.minecraft.world.entity.EntityType @@ -20,8 +20,8 @@ import org.bukkit.Bukkit.getPlayer import org.bukkit.Color import org.bukkit.Location import org.bukkit.block.BlockFace -import org.bukkit.craftbukkit.v1_20_R3.CraftServer -import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay +import org.bukkit.craftbukkit.CraftServer +import org.bukkit.craftbukkit.entity.CraftTextDisplay import org.bukkit.util.Transformation import org.joml.Quaternionf import org.joml.Vector3f @@ -101,12 +101,6 @@ abstract class Display( fun resetPosition(parent: TextDisplayHandler) { val location = getLocation(parent) - entity.teleportTo( - location.x, - location.y, - location.z - ) - entity.setTransformation(com.mojang.math.Transformation( Vector3f(0f), ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), @@ -114,7 +108,10 @@ abstract class Display( Quaternionf() )) - shownPlayers.map(::getPlayer).forEach { it?.minecraft?.connection?.send(ClientboundTeleportEntityPacket(entity)) } + shownPlayers.map(::getPlayer).forEach { player -> + if (player == null) return@forEach + moveDisplayEntityPacket(player.minecraft, entity, location.x, location.y, location.z) + } } /** Registers this display handler */ @@ -149,9 +146,9 @@ abstract class Display( setText(getText()) val chunk = entity.level().world.getChunkAtIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return - val playerChunk = chunk.minecraft.playerChunk ?: return - - val viewers = playerChunk.getPlayers(false).toSet() + val playerChunk = chunk.minecraft.`moonrise$getChunkAndHolder`().holder.playerProvider ?: return + //TODO fix this its bad + val viewers = playerChunk.getPlayers(chunk.minecraft.pos, false).toSet() val newPlayers = viewers.filterNot { shownPlayers.contains(it.uuid) } val old = viewers.filter { shownPlayers.contains(it.uuid) } @@ -167,7 +164,7 @@ abstract class Display( } private fun update(player: ServerPlayer) { - entity.entityData.refresh(player) + entity.refreshEntityData(player) } private fun broadcast(player: ServerPlayer) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt index 7172cd88f4..eea1a47864 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt @@ -9,7 +9,7 @@ import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW -import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay +import org.bukkit.craftbukkit.entity.CraftTextDisplay class FlowMeterDisplay( private val meter: PowerNode.PowerFlowMeter, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt index 688795d043..540244b9a7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt @@ -8,7 +8,7 @@ import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration -import org.bukkit.craftbukkit.v1_20_R3.entity.CraftTextDisplay +import org.bukkit.craftbukkit.entity.CraftTextDisplay class SimpleFluidDisplay( storage: StorageContainer, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 6f3b101f98..9c54abace4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -1,11 +1,11 @@ package net.horizonsend.ion.server.features.custom.blocks import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap -import net.horizonsend.ion.server.features.custom.items.CustomBlockItem import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.miscellaneous.utils.getMatchingMaterials import net.horizonsend.ion.server.miscellaneous.utils.map import net.horizonsend.ion.server.miscellaneous.utils.nms @@ -44,7 +44,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_ALUMINUM) ) - ) { CustomItems.ALUMINUM_ORE }) + ) { CustomItemRegistry.ALUMINUM_ORE }) val ALUMINUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "ALUMINUM_BLOCK", @@ -53,7 +53,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ALUMINUM_BLOCK) ) - ) { CustomItems.ALUMINUM_BLOCK }) + ) { CustomItemRegistry.ALUMINUM_BLOCK }) val RAW_ALUMINUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "RAW_ALUMINUM_BLOCK", @@ -62,7 +62,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_ALUMINUM_BLOCK) ) - ) { CustomItems.RAW_ALUMINUM_BLOCK }) + ) { CustomItemRegistry.RAW_ALUMINUM_BLOCK }) val CHETHERITE_ORE : CustomBlock = register(CustomBlock( identifier = "CHETHERITE_ORE", @@ -71,7 +71,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::CHETHERITE) ) - ) { CustomItems.CHETHERITE_ORE }) + ) { CustomItemRegistry.CHETHERITE_ORE }) val STEEL_BLOCK : CustomBlock = register(CustomBlock( identifier = "STEEL_BLOCK", @@ -80,7 +80,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::STEEL_BLOCK) ) - ) { CustomItems.STEEL_BLOCK }) + ) { CustomItemRegistry.STEEL_BLOCK }) val CHETHERITE_BLOCK : CustomBlock = register(CustomBlock( identifier = "CHETHERITE_BLOCK", @@ -89,7 +89,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::CHETHERITE_BLOCK) ) - ) { CustomItems.CHETHERITE_BLOCK }) + ) { CustomItemRegistry.CHETHERITE_BLOCK }) val TITANIUM_ORE : CustomBlock = register(CustomBlock( identifier = "TITANIUM_ORE", @@ -98,7 +98,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_TITANIUM) ) - ) { CustomItems.TITANIUM_ORE }) + ) { CustomItemRegistry.TITANIUM_ORE }) val TITANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "TITANIUM_BLOCK", @@ -107,7 +107,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::TITANIUM_BLOCK) ) - ) { CustomItems.TITANIUM_BLOCK }) + ) { CustomItemRegistry.TITANIUM_BLOCK }) val RAW_TITANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "RAW_TITANIUM_BLOCK", @@ -116,7 +116,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_TITANIUM_BLOCK) ) - ) { CustomItems.RAW_TITANIUM_BLOCK }) + ) { CustomItemRegistry.RAW_TITANIUM_BLOCK }) val URANIUM_ORE : CustomBlock = register(CustomBlock( identifier = "URANIUM_ORE", @@ -125,7 +125,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_URANIUM) ) - ) { CustomItems.URANIUM_ORE }) + ) { CustomItemRegistry.URANIUM_ORE }) val URANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "URANIUM_BLOCK", @@ -134,7 +134,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::URANIUM_BLOCK) ) - ) { CustomItems.URANIUM_BLOCK }) + ) { CustomItemRegistry.URANIUM_BLOCK }) val ENRICHED_URANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "ENRICHED_URANIUM_BLOCK", @@ -143,7 +143,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ENRICHED_URANIUM_BLOCK) ) - ) { CustomItems.ENRICHED_URANIUM_BLOCK }) + ) { CustomItemRegistry.ENRICHED_URANIUM_BLOCK }) val NETHERITE_CASING : CustomBlock = register(CustomBlock( identifier = "NETHERITE_CASING", @@ -152,7 +152,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::NETHERITE_CASING) ) - ) { CustomItems.NETHERITE_CASING }) + ) { CustomItemRegistry.NETHERITE_CASING }) val RAW_URANIUM_BLOCK : CustomBlock = register(CustomBlock( identifier = "RAW_URANIUM_BLOCK", @@ -161,7 +161,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::RAW_URANIUM_BLOCK) ) - ) { CustomItems.RAW_ALUMINUM_BLOCK }) + ) { CustomItemRegistry.RAW_ALUMINUM_BLOCK }) val SUPERCONDUCTOR_BLOCK : CustomBlock = register(CustomBlock( identifier = "SUPERCONDUCTOR_BLOCK", @@ -170,7 +170,7 @@ object CustomBlocks { requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::SUPERCONDUCTOR_BLOCK) ) - ) { CustomItems.SUPERCONDUCTOR_BLOCK }) + ) { CustomItemRegistry.SUPERCONDUCTOR_BLOCK }) val BATTLECRUISER_REACTOR_CORE : CustomBlock = register(CustomBlock( identifier = "BATTLECRUISER_REACTOR_CORE", @@ -179,7 +179,7 @@ object CustomBlocks { requiredTool = null, drops = customItemDrop(CustomItemRegistry::BATTLECRUISER_REACTOR_CORE) ) - ) { CustomItems.BATTLECRUISER_REACTOR_CORE }) + ) { CustomItemRegistry.BATTLECRUISER_REACTOR_CORE }) val BARGE_REACTOR_CORE : CustomBlock = register(CustomBlock( identifier = "BARGE_REACTOR_CORE", @@ -188,7 +188,7 @@ object CustomBlocks { requiredTool = null, drops = customItemDrop(CustomItemRegistry::BARGE_REACTOR_CORE) ) - ) { CustomItems.BARGE_REACTOR_CORE }) + ) { CustomItemRegistry.BARGE_REACTOR_CORE }) val CRUISER_REACTOR_CORE : CustomBlock = register(CustomBlock( identifier = "CRUISER_REACTOR_CORE", @@ -197,7 +197,7 @@ object CustomBlocks { requiredTool = null, drops = customItemDrop(CustomItemRegistry::CRUISER_REACTOR_CORE) ) - ) { CustomItems.CRUISER_REACTOR_CORE }) + ) { CustomItemRegistry.CRUISER_REACTOR_CORE }) private fun customItemDrop(customItem: Supplier, amount: Int = 1): Supplier> { return customItem.map { item -> listOf(item.constructItemStack(amount)) } @@ -205,7 +205,7 @@ object CustomBlocks { val MULTIBLOCK_WORKBENCH = register(MultiblockWorkbench) - private fun customItemDrop(identifier: String, amount: Int = 1): Supplier> { + fun customItemDrop(identifier: String, amount: Int = 1): Supplier> { val customItem = CustomItemRegistry.getByIdentifier(identifier)?.constructItemStack() ?: return Supplier { listOf() } customItem.amount = amount diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt index cf04e955dc..31a202f6a7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.custom.blocks -import net.horizonsend.ion.server.features.custom.items.CustomBlockItem +import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import org.bukkit.block.Block import org.bukkit.block.data.BlockData import org.bukkit.event.player.PlayerInteractEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 2ed01c0059..ddb83b82ae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,9 +1,10 @@ package net.horizonsend.ion.server.features.custom.blocks +import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop -import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiText import net.horizonsend.ion.server.features.gui.custom.misc.anvilinput.TextInputMenu @@ -17,9 +18,11 @@ import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilbloc import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.setDisplayNameAndGet import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.text.loreName +import net.horizonsend.ion.server.miscellaneous.utils.updateData +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updateLore import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text @@ -44,9 +47,9 @@ object MultiblockWorkbench : InteractableCustomBlock( blockData = CustomBlocks.mushroomBlockData(setOf(BlockFace.NORTH, BlockFace.DOWN, BlockFace.EAST)), drops = BlockLoot( requiredTool = null, - drops = customItemDrop(CustomItems::MULTIBLOCK_WORKBENCH, 1) + drops = customItemDrop("MULTIBLOCK_WORKBENCH", 1) ), - customBlockItem = { CustomItems.MULTIBLOCK_WORKBENCH } + customBlockItem = { CustomItemRegistry.MULTIBLOCK_WORKBENCH } ) { private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) @@ -85,23 +88,18 @@ object MultiblockWorkbench : InteractableCustomBlock( override fun setup(view: InventoryView) { lockedSlots.addAll(BACKGROUND_SLOTS) - addGuiButton(LEFT_BUTTON_SLOT, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { - it.setCustomModelData(GuiItem.LEFT.customModelData) - it.displayName(text("Previous Multiblock").itemName) - }) { + + addGuiButton(LEFT_BUTTON_SLOT, GuiItem.LEFT.makeItem(text("Previous Multiblock"))) { multiblockIndex = (multiblockIndex - 1).coerceAtLeast(0) refreshMultiblock(it.view) } - addGuiButton(RIGHT_BUTTON_SLOT, ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { - it.setCustomModelData(GuiItem.RIGHT.customModelData) - it.displayName(text("Next Multiblock").itemName) - }) { + addGuiButton(RIGHT_BUTTON_SLOT, GuiItem.RIGHT.makeItem(text("Next Multiblock"))) { multiblockIndex = (multiblockIndex + 1).coerceAtMost(multiblocks.lastIndex) refreshMultiblock(it.view) } - addGuiButton(SEARCH_BUTTON_SLOT, ItemStack(Material.NAME_TAG).setDisplayNameAndGet(text("Search").itemName)) { + addGuiButton(SEARCH_BUTTON_SLOT, ItemStack(Material.NAME_TAG).updateDisplayName(text("Search"))) { openSearchMenu(it.playerClicker) } @@ -158,6 +156,7 @@ object MultiblockWorkbench : InteractableCustomBlock( val item = inventory.contents[CONFIRM_BUTTON_SLOT] ?: return@sync val missing = checkRequirements(getUnlockedItems(), currentMultiblock) + // TODO rewrite this if (missing.isNotEmpty()) { item.type = Material.BARRIER val missingLore = missing @@ -175,11 +174,10 @@ object MultiblockWorkbench : InteractableCustomBlock( } item.type = Material.WARPED_FUNGUS_ON_A_STICK - item.updateMeta { - it.lore(listOf()) - it.displayName(text("Packaged multiblock ready!", GREEN).itemName) - it.setCustomModelData(GuiItem.CHECKMARK.customModelData ) - } + + item.updateLore(listOf()) + item.updateDisplayName(text("Packaged multiblock ready!", GREEN)) + item.updateData(DataComponentTypes.ITEM_MODEL, GuiItem.CHECKMARK.modelKey) ready = true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItem.kt index 9a9de2b574..9d0d2938a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItem.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.features.custom.items.component.CustomItemComp import net.horizonsend.ion.server.features.custom.items.component.LoreManager import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.custom.items.util.serialization.SerializationManager -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.kyori.adventure.text.Component import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index e3e0b12162..ae3646c72e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -14,6 +14,11 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.items.CustomItemListeners.sortCustomItemListeners import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.custom.items.component.Smeltable +import net.horizonsend.ion.server.features.custom.items.misc.MultiblockToken +import net.horizonsend.ion.server.features.custom.items.misc.MultimeterItem +import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock +import net.horizonsend.ion.server.features.custom.items.misc.TransportFilterItem +import net.horizonsend.ion.server.features.custom.items.misc.Wrench import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporter @@ -40,7 +45,8 @@ import net.horizonsend.ion.server.features.custom.items.util.ItemFactory.Preset. import net.horizonsend.ion.server.features.custom.items.util.withComponent import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.CUSTOM_ITEM +import net.horizonsend.ion.server.features.transport.filters.FilterBlocks +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.map import net.horizonsend.ion.server.miscellaneous.utils.text.itemName @@ -313,6 +319,20 @@ object CustomItemRegistry : IonServerComponent() { val CRATE_PLACER = register(CratePlacer) + val MULTIMETER = register(MultimeterItem) + + val MULTIBLOCK_TOKEN = register(MultiblockToken) + val PACKAGED_MULTIBLOCK = register(PackagedMultiblock) + val MULTIBLOCK_WORKBENCH = register(CustomBlockItem( + identifier = "MULTIBLOCK_WORKBENCH", + displayName = text("Multiblock Workbench").itemName, + customModel = "misc/multiblock_workbench" + ) { CustomBlocks.MULTIBLOCK_WORKBENCH }) + + val WRENCH = register(Wrench) + + val FLUID_FILTER: TransportFilterItem = register(TransportFilterItem("FLUID_FILTER", text("Fluid Filter").itemName) { FilterBlocks.FLUID_FILTER }) + private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( text("$tierName ", tierColor), text("Power ", GOLD), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/GasStorage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/GasStorage.kt index d363df36bb..011c8d4d6e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/GasStorage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/GasStorage.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.custom.items.util.serialization.Seria import net.horizonsend.ion.server.features.custom.items.util.serialization.token.IntegerToken import net.horizonsend.ion.server.features.custom.items.util.updateDurability import net.horizonsend.ion.server.features.gas.type.Gas -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.text.Component import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/ModManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/ModManager.kt index 8a92fa54aa..ba5c41899f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/ModManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/ModManager.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModif import net.horizonsend.ion.server.features.custom.items.util.serialization.SerializationManager import net.horizonsend.ion.server.features.custom.items.util.serialization.token.ItemModificationToken import net.horizonsend.ion.server.features.custom.items.util.serialization.token.ListToken -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.TOOL_MODIFICATIONS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.TOOL_MODIFICATIONS import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index 190977b9ab..fc26f5e73e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -4,48 +4,48 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.rightClickListener +import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.PrePackaged.getTokenData import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.text.itemName -import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updateLore +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GRAY -import net.kyori.adventure.text.format.TextDecoration.ITALIC -import org.bukkit.Material -import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataType import java.util.Locale -object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { - override fun constructItemStack(): ItemStack { - val base = ItemStack(Material.PAPER).updateMeta { - it.persistentDataContainer.set(CUSTOM_ITEM, PersistentDataType.STRING, identifier) - it.displayName(text("Pre-Packaged Multiblock").decoration(ITALIC, false)) - } - - return base +object MultiblockToken : CustomItem( + "MULTIBLOCK_TOKEN", + text("Pre-Packaged Multiblock"), + ItemFactory.unStackableCustomItem +) { + override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@MultiblockToken) { event, _, itemStack -> + handleSecondaryInteract(event.player, itemStack, event) + }) } fun constructFor(multiblock: Multiblock): ItemStack { val base = constructItemStack() - - return base.updateMeta { - PrePackaged.setTokenData(multiblock, it.persistentDataContainer) - it.displayName(ofChildren(multiblock.getDisplayName(), text(" Token")).itemName) - it.lore(listOf( + .updateDisplayName(ofChildren(multiblock.getDisplayName(), text(" Token"))) + .updateLore(listOf( text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", GRAY).itemName, text("Variant: ${multiblock.javaClass.simpleName}", GRAY).itemName )) - } + + return base.updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } } - override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + private fun handleSecondaryInteract(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { if (itemStack.type.isAir) return val packagedData = getTokenData(itemStack) ?: run { @@ -53,10 +53,6 @@ object MultiblockToken : CustomItem("MULTIBLOCK_TOKEN") { return } - if (livingEntity !is Player) return - - if (event == null) return - val origin = PrePackaged.getOriginFromPlacement( event.clickedBlock ?: return, livingEntity.facing, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 89f0c5b6ed..ed5e3f17b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -7,6 +7,11 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.leftClickListener +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.rightClickListener +import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.PathfindingNodeWrapper @@ -15,7 +20,6 @@ import net.horizonsend.ion.server.features.transport.util.getHeuristic import net.horizonsend.ion.server.features.transport.util.getNeighbors import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.NODE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z @@ -29,28 +33,27 @@ import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.audience.Audience import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import net.kyori.adventure.text.format.TextDecoration -import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataType import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG import java.util.PriorityQueue -object MultimeterItem : CustomItem("MULTIMETER") { - override fun constructItemStack(): ItemStack { - return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { - it.displayName(Component.text("Multimeter", NamedTextColor.YELLOW).decoration(TextDecoration.ITALIC, false)) - it.persistentDataContainer.set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, identifier) - } +object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", NamedTextColor.YELLOW), ItemFactory.unStackableCustomItem) { + override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@MultimeterItem) { event, _, itemStack -> + handleSecondaryInteract(event.player, itemStack, event) + }) + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@MultimeterItem) { event, _, itemStack -> + handlePrimaryInteract(event.player, itemStack, event) + }) } - override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + private fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { val targeted = livingEntity.getTargetBlock(null, 10) val key = toBlockKey(targeted.x, targeted.y, targeted.z) @@ -63,7 +66,7 @@ object MultimeterItem : CustomItem("MULTIMETER") { tryCheckResistance(livingEntity, livingEntity.world, itemStack) } - override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + private fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { if (livingEntity !is Player) return if (livingEntity.isSneaking) { cycleNetworks(livingEntity, livingEntity.world, itemStack) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index c1e851ad0a..967b479737 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -5,32 +5,41 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.leftClickListener +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.rightClickListener +import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.Material import org.bukkit.block.Chest import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.BlockStateMeta -import org.bukkit.persistence.PersistentDataType.STRING import java.util.Locale -object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { - override fun constructItemStack(): ItemStack { - return ItemStack(Material.CHEST).updateMeta { - it.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) - } +object PackagedMultiblock : CustomItem( + "PACKAGED_MULTIBLOCK", + ofChildren(Component.text("Packaged Null")), + ItemFactory.unStackableCustomItem +) { + override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@PackagedMultiblock) { event, _, itemStack -> + handleSecondaryInteract(event.player, itemStack, event) + }) + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@PackagedMultiblock) { event, _, itemStack -> + handlePrimaryInteract(event.player, itemStack, event) + }) } fun createFor(multiblock: Multiblock): ItemStack { @@ -46,7 +55,7 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { } } - override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + private fun handleSecondaryInteract(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { if (itemStack.type.isAir) return val packagedData = PrePackaged.getTokenData(itemStack) ?: run { @@ -56,10 +65,6 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { val inventory = ((itemStack.itemMeta as? BlockStateMeta)?.blockState as? Chest)?.inventory ?: return livingEntity.userError("The packaged multiblock has no data!") - if (livingEntity !is Player) return - - if (event == null) return - val direction = livingEntity.facing val origin = PrePackaged.getOriginFromPlacement( event.clickedBlock ?: return, @@ -92,7 +97,7 @@ object PackagedMultiblock : CustomItem("PACKAGED_MULTIBLOCK") { itemStack.amount-- } - override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { if (livingEntity !is Player) return val packagedData = PrePackaged.getTokenData(itemStack) ?: run { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt index ad0c1e7bd6..637224efb0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.custom.items.misc import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.transport.filters.FilterBlock import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM @@ -16,8 +17,12 @@ import org.bukkit.inventory.meta.BlockStateMeta import org.bukkit.persistence.PersistentDataType.STRING import java.util.function.Supplier -class TransportFilterItem(identifier: String, val displayName: Component, private val filterBlock: Supplier>) : CustomItem(identifier) { - override fun constructItemStack(): ItemStack { +class TransportFilterItem(identifier: String, displayName: Component, private val filterBlock: Supplier>) : CustomItem( + identifier, + displayName, + ItemFactory.stackableCustomItem +) { + fun constructItemStackB(): ItemStack { return ItemStack(Material.BARREL).updateMeta { meta -> meta as BlockStateMeta meta.blockState = filterBlock.get().createState() @@ -33,9 +38,7 @@ class TransportFilterItem(identifier: String, val displayName: Component, privat } } - override val cancelSecondaryInteract: Boolean = false - - override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { if (event == null) return event.isCancelled = false } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index 9bccacf307..f2b572ee46 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -3,31 +3,35 @@ package net.horizonsend.ion.server.features.custom.items.misc import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.leftClickListener +import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.rightClickListener +import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.PrePackaged -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.isWallSign -import net.horizonsend.ion.server.miscellaneous.utils.text.itemName -import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text -import org.bukkit.Material import org.bukkit.block.Sign import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataType - -object Wrench : CustomItem("WRENCH") { - override fun constructItemStack(): ItemStack { - return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK).updateMeta { - it.setCustomModelData(8000) - it.displayName(text("Wrench").itemName) - it.persistentDataContainer.set(CUSTOM_ITEM, PersistentDataType.STRING, identifier) - } + +object Wrench : CustomItem( + "WRENCH", + text("Wrench"), + ItemFactory.unStackableCustomItem +) { + override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@Wrench) { event, _, itemStack -> + handleSecondaryInteract(event.player, event) + }) + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@Wrench) { event, _, itemStack -> + handlePrimaryInteract(event.player, event) + }) } - override fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + private fun handlePrimaryInteract(livingEntity: LivingEntity, event: PlayerInteractEvent) { if (livingEntity !is Player) return val hitBlock = event.clickedBlock @@ -44,7 +48,7 @@ object Wrench : CustomItem("WRENCH") { MultiblockCommand.onCheck(livingEntity, multiblock, sign.x, sign.y, sign.z) } - override fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + private fun handleSecondaryInteract(livingEntity: LivingEntity, event: PlayerInteractEvent?) { if (livingEntity !is Player) return val clickedBlock = event?.clickedBlock ?: return val state = clickedBlock.state diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/ProgressHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/ProgressHolder.kt index 1195523ce7..77a6db6457 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/ProgressHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/ProgressHolder.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.util.ItemFactory -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.updateLore import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/armor/PowerArmorItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/armor/PowerArmorItem.kt index 38b029d70f..dfe331aa82 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/armor/PowerArmorItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/armor/PowerArmorItem.kt @@ -22,7 +22,7 @@ import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.world.IonWorld.Companion.hasFlag import net.horizonsend.ion.server.features.world.WorldFlag -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.kyori.adventure.key.Key import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/Battery.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/Battery.kt index 0fa7ef1c28..c9f7e339bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/Battery.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/Battery.kt @@ -7,9 +7,9 @@ import net.horizonsend.ion.server.features.custom.items.component.CustomItemComp import net.horizonsend.ion.server.features.custom.items.component.Listener import net.horizonsend.ion.server.features.custom.items.component.PowerStorage import net.horizonsend.ion.server.features.custom.items.util.ItemFactory -import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.multiblock.Multiblocks -import net.horizonsend.ion.server.features.multiblock.type.PowerStoringMultiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE @@ -36,20 +36,31 @@ class Battery(type: Char, color: TextColor, maxPower: Int) : CustomItem( val clickedType = clickedBlock.type if (!clickedType.isWallSign) return - val sign = clickedBlock.getState(false) as? Sign ?: return - val multiblock = Multiblocks[sign] as? PowerStoringMultiblock ?: return + val sign = event.clickedBlock?.state as? Sign ?: return + val multiblock = MultiblockAccess.getFast(sign) ?: return + if (multiblock !is EntityMultiblock<*>) return + + val entity = multiblock.getMultiblockEntity(sign) ?: return + if (entity !is PoweredMultiblockEntity) return + + handleBatteryInput(entity, event) + } + + private fun handleBatteryInput(entity: PoweredMultiblockEntity, event: PlayerInteractEvent) { + val item = event.item ?: return val power = getComponent(CustomComponentTypes.POWER_STORAGE).getPower(item) var powerToTransfer = power * item.amount if (powerToTransfer == 0) return - val machinePower = PowerMachines.getPower(sign) - val maxMachinePower = multiblock.maxPower + val machinePower = entity.powerStorage.getPower() + val maxMachinePower = entity.powerStorage.capacity + if (maxMachinePower - machinePower < powerToTransfer) { powerToTransfer = maxMachinePower - machinePower } getComponent(CustomComponentTypes.POWER_STORAGE).setPower(this, item, power - powerToTransfer / item.amount) - PowerMachines.addPower(sign, powerToTransfer) + entity.powerStorage.addPower(powerToTransfer) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerChainsaw.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerChainsaw.kt index 12acbc1948..ef7674fafa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerChainsaw.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerChainsaw.kt @@ -10,12 +10,12 @@ import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModif import net.horizonsend.ion.server.features.custom.items.type.tool.mods.general.AutoReplantModifier import net.horizonsend.ion.server.features.custom.items.type.tool.mods.tool.chainsaw.ExtendedBar import net.horizonsend.ion.server.features.multiblock.type.farming.Crop +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toLocation import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isFence import net.horizonsend.ion.server.miscellaneous.utils.isLeaves import net.horizonsend.ion.server.miscellaneous.utils.isLog import net.horizonsend.ion.server.miscellaneous.utils.isWood -import net.horizonsend.ion.server.miscellaneous.utils.toLocation import net.kyori.adventure.text.Component import net.minecraft.core.BlockPos import org.bukkit.GameMode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerDrill.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerDrill.kt index b6ee841662..d24fae3208 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerDrill.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerDrill.kt @@ -9,10 +9,10 @@ import net.horizonsend.ion.server.features.custom.items.component.Listener.Compa import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModification import net.horizonsend.ion.server.features.custom.items.type.tool.mods.drops.DropModifier import net.horizonsend.ion.server.features.custom.items.type.tool.mods.drops.DropSource +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toLocation import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockData import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.toLocation import net.kyori.adventure.text.Component import net.minecraft.core.BlockPos import net.minecraft.world.level.block.BaseFireBlock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerHoe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerHoe.kt index 064da3f0aa..dd78c39e47 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerHoe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/PowerHoe.kt @@ -11,8 +11,8 @@ import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ItemModif import net.horizonsend.ion.server.features.custom.items.type.tool.mods.drops.DropModifier import net.horizonsend.ion.server.features.custom.items.type.tool.mods.drops.DropSource import net.horizonsend.ion.server.features.multiblock.type.farming.Crop +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toLocation import net.horizonsend.ion.server.miscellaneous.utils.enumSetOf -import net.horizonsend.ion.server.miscellaneous.utils.toLocation import net.kyori.adventure.text.Component import net.minecraft.core.BlockPos import org.bukkit.FluidCollisionMode diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt index 74507aa1d7..6c9a72dee5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/tool/mods/ToolModMenu.kt @@ -171,7 +171,7 @@ class ToolModMenu( val player = event.player val holder = player.openInventory.topInventory.holder - if (ToolModMenu) { + if (holder is ToolModMenu) { // Assume they dropped the item if (event.itemDrop.itemStack.itemMeta == holder.itemStack.itemMeta) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/sword/EnergySword.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/sword/EnergySword.kt index 7661c8da8b..deaafa3255 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/sword/EnergySword.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/weapon/sword/EnergySword.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.features.custom.items.component.Listener.Compa import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.leftClickListener import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.prepareCraftListener import net.horizonsend.ion.server.features.custom.items.util.ItemFactory -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.kyori.adventure.key.Key.key import net.kyori.adventure.sound.Sound diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/ItemFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/ItemFactory.kt index 5ecd4b284e..e2cfb6203e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/ItemFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/util/ItemFactory.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.custom.items.util import io.papermc.paper.datacomponent.DataComponentType import io.papermc.paper.datacomponent.DataComponentTypes import io.papermc.paper.datacomponent.item.ItemLore -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys.HORIZONSEND_NAMESPACE +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.HORIZONSEND_NAMESPACE import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.key.Key import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt index d5de1a5460..1fd78f7d45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.gui.custom.settings.SettingsPageGui import net.horizonsend.ion.server.features.nations.gui.skullItem -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt index b6aef21e2f..87504964f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/machine/CryoPods.kt @@ -10,8 +10,8 @@ import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.bukkitLocation import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toChunkLocal import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId -import net.horizonsend.ion.server.miscellaneous.utils.toChunkLocal import org.bukkit.Bukkit import org.bukkit.World import org.bukkit.block.Sign diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt index c5de880540..30f58e2169 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.crafting import io.papermc.paper.util.Tick import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.furnaceFuelIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.furnaceSmeltingIngredient import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient @@ -36,9 +36,9 @@ object MultiblockRecipes : IonServerComponent() { val URANIUM_ENRICHMENT = registerRecipe(ProcessingMultiblockRecipe( multiblock = CentrifugeMultiblock, multiblockEntityClass = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.URANIUM, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.URANIUM, 1), result = MultiRecipeResult( - furnaceRecipeResult(CustomItems.ENRICHED_URANIUM), + furnaceRecipeResult(CustomItemRegistry.ENRICHED_URANIUM), SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) ), resources = listOf(PowerIngredient(100)), @@ -47,10 +47,10 @@ object MultiblockRecipes : IonServerComponent() { val URANIUM_CORE_COMPRESSION = registerRecipe(ProcessingMultiblockRecipe( multiblock = CompressorMultiblock, multiblockEntityClass = CompressorMultiblock.CompressorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.URANIUM_CORE, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.URANIUM_CORE, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.URANIUM_ROD)), + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.URANIUM_ROD)), SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f) ) )) @@ -59,18 +59,18 @@ object MultiblockRecipes : IonServerComponent() { multiblock = GasFurnaceMultiblock, multiblockEntityClass = GasFurnaceMultiblock.GasFurnaceMultiblockEntity::class, smelting = furnaceSmeltingIngredient(ItemStack(Material.IRON_INGOT), 1), - fuel = furnaceFuelIngredient(CustomItems.GAS_CANISTER_OXYGEN, 5), + fuel = furnaceFuelIngredient(CustomItemRegistry.GAS_CANISTER_OXYGEN, 5), resources = listOf(PowerIngredient(100)), - result = furnaceRecipeResult(CustomItems.STEEL_INGOT) + result = furnaceRecipeResult(CustomItemRegistry.STEEL_INGOT) )) val REACTIVE_PLATING_PRESSING = registerRecipe(ProcessingMultiblockRecipe( multiblock = PlatePressMultiblock, multiblockEntityClass = PlatePressMultiblock.PlatePressMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.REACTIVE_PLATING, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.REACTIVE_PLATING, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.REACTIVE_CHASSIS)), + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.REACTIVE_CHASSIS)), SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f) ) )) @@ -78,10 +78,10 @@ object MultiblockRecipes : IonServerComponent() { val STEEL_PLATE_PRESSING = registerRecipe(ProcessingMultiblockRecipe( multiblock = PlatePressMultiblock, multiblockEntityClass = PlatePressMultiblock.PlatePressMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.STEEL_PLATE, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.STEEL_PLATE, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.STEEL_CHASSIS)), + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.STEEL_CHASSIS)), SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f) ) )) @@ -89,10 +89,10 @@ object MultiblockRecipes : IonServerComponent() { val FUEL_ROD_CORE_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( multiblock = FabricatorMultiblock, multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.FUEL_ROD_CORE, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.FUEL_ROD_CORE, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItems.FUEL_CELL)), + ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItemRegistry.FUEL_CELL)), SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) @@ -100,10 +100,10 @@ object MultiblockRecipes : IonServerComponent() { val FABRICATED_ASSEMBLY_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( multiblock = FabricatorMultiblock, multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.REACTIVE_ASSEMBLY, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.REACTIVE_ASSEMBLY, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItems.FABRICATED_ASSEMBLY)), + ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItemRegistry.FABRICATED_ASSEMBLY)), SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) @@ -111,10 +111,10 @@ object MultiblockRecipes : IonServerComponent() { val REINFORCED_FRAME_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( multiblock = FabricatorMultiblock, multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.STEEL_ASSEMBLY, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.STEEL_ASSEMBLY, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItems.REINFORCED_FRAME)), + ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItemRegistry.REINFORCED_FRAME)), SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) @@ -122,10 +122,10 @@ object MultiblockRecipes : IonServerComponent() { val CIRCUIT_BOARD_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( multiblock = CircuitfabMultiblock, multiblockEntityClass = CircuitfabMultiblock.CircuitfabMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.CIRCUITRY, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.CIRCUITRY, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.CIRCUIT_BOARD)), + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.CIRCUIT_BOARD)), SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) @@ -133,10 +133,10 @@ object MultiblockRecipes : IonServerComponent() { val LOADED_SHELL_LOADING = registerRecipe(ProcessingMultiblockRecipe( multiblock = AmmoLoaderMultiblock, multiblockEntityClass = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.UNLOADED_SHELL, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.UNLOADED_SHELL, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItems.LOADED_SHELL)), + ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.LOADED_SHELL)), SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) @@ -144,10 +144,10 @@ object MultiblockRecipes : IonServerComponent() { val UNCHARGED_SHELL_CHARGING = registerRecipe(ProcessingMultiblockRecipe( multiblock = AmmoLoaderMultiblock, multiblockEntityClass = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.UNCHARGED_SHELL, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.UNCHARGED_SHELL, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItems.CHARGED_SHELL)), + ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.CHARGED_SHELL)), SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) @@ -155,10 +155,10 @@ object MultiblockRecipes : IonServerComponent() { val ARSENAL_MISSILE_LOADING = registerRecipe(ProcessingMultiblockRecipe( multiblock = MissileLoaderMultiblock, multiblockEntityClass = MissileLoaderMultiblock.MissileLoaderMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItems.UNLOADED_ARSENAL_MISSILE, 1), + smelting = furnaceSmeltingIngredient(CustomItemRegistry.UNLOADED_ARSENAL_MISSILE, 1), resources = listOf(PowerIngredient(100)), result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItems.ARSENAL_MISSILE)), + ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.ARSENAL_MISSILE)), SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f) ), )) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt index 8b8b7673ae..33c4c9dbae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.crafting.ingredient -import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem -import net.horizonsend.ion.server.features.custom.items.GasCanister +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt index a987691563..303d6d7c70 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.crafting.ingredient import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.custom.items.GasCanister +import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import org.bukkit.inventory.FurnaceInventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt index 784f3ce64e..badfc3cf0f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt @@ -1,10 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.ticked -import com.nijiko.permissions.ModularControl.tickInterval - interface TickedMultiblockEntityParent { val tickingManager: TickingManager - + /** * **/ @@ -25,7 +23,7 @@ interface TickedMultiblockEntityParent { } currentTick++ - if (currentTick >= tickInterval) { + if (currentTick >= interval) { currentTick = 0 return false } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index 1624d686ec..bf78cff7e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -42,7 +42,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag } override fun markChanged() { - chunk.inner.minecraft.isUnsaved = true + chunk.inner.minecraft.markUnsaved() } override fun getNetwork(type: CacheType): TransportCache { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index d83cb23fae..a736075d82 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -4,8 +4,8 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING -import net.horizonsend.ion.server.features.custom.items.CustomBlockItem -import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index 98726773b0..93f46c4ddc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -20,7 +20,6 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.kyori.adventure.text.Component.text import org.bukkit.Material -import org.bukkit.Material.matchMaterial import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -190,7 +189,7 @@ abstract class AmmoPressMultiblock : Multiblock(), EntityMultiblock result.amount.toDouble() } ?: return - val delta = IonServer.globalGassesConfiguration.collectorTickInterval / 20L + val delta = globalGassesConfiguration().collectorTickInterval / 20L val amount = (random.amount * weight) * (delta) Tasks.sync { tryHarvestGas(furnaceInventory, hopperInventory, random.gas, amount.roundToInt()) } @@ -110,14 +111,14 @@ object CanisterGasCollectorMultiblock : Multiblock(), EntityMultiblock fillEmptyCanister(furnaceInventory, gas, amount) + CustomItemRegistry.GAS_CANISTER_EMPTY -> fillEmptyCanister(furnaceInventory, gas, amount) is GasCanister -> fillGasCanister(canisterItem, furnaceInventory, hopperInventory, amount) // Don't even bother with the gas else -> false } } private fun fillEmptyCanister(furnaceInventory: FurnaceInventory, gas: Gas, amount: Int): Boolean { - val newType = CustomItems.getByIdentifier(gas.containerIdentifier) as? GasCanister ?: return false + val newType = CustomItemRegistry.getByIdentifier(gas.containerIdentifier) as? GasCanister ?: return false val newCanister = newType.createWithFill(amount) furnaceInventory.fuel = newCanister diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index eb4379a51d..c341d2fa8a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -25,6 +25,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.event.inventory.FurnaceBurnEvent +import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMultiblock, FurnaceMultiblock, DisplayNameMultilblock { @@ -115,15 +116,10 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMul if (availablePower == 0) return val item = event.fuel - if (isPowerable(item)) { - handleLegacy(item, event, furnace, availablePower) - } - - val custom = item.customItem val custom = item.customItem ?: return if (custom.hasComponent(CustomComponentTypes.POWER_STORAGE)) - handleModern(item, custom, custom.getComponent(CustomComponentTypes.POWER_STORAGE), event, furnace, inventory, sign, power) + handleModern(item, custom, custom.getComponent(CustomComponentTypes.POWER_STORAGE), event, furnace, furnace.inventory, powerStorage.getPower()) } fun handleModern( @@ -133,7 +129,6 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMul event: FurnaceBurnEvent, furnace: Furnace, inventory: FurnaceInventory, - sign: Sign, power: Int ) { if (powerManager.getMaxPower(customItem, item) == powerManager.getPower(item)) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index b64f685ebe..7e18c2033a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -21,19 +21,21 @@ import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.RED import net.minecraft.server.MinecraftServer import net.minecraft.world.item.crafting.RecipeType +import net.minecraft.world.item.crafting.SingleRecipeInput import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Furnace import org.bukkit.block.Sign -import org.bukkit.craftbukkit.v1_20_R3.block.CraftFurnaceFurnace -import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack -import org.bukkit.inventory.ItemStack +import org.bukkit.craftbukkit.block.CraftFurnaceFurnace +import org.bukkit.craftbukkit.inventory.CraftItemStack +import org.bukkit.inventory.ItemStack as BukkitItemStack import java.util.Optional abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMultiblock { @@ -116,8 +118,14 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu return } + val smelted = furnace.inventory.smelting + if (smelted == null) { + sleepWithStatus(text("Sleeping...", BLUE), 250) + return + } + if (furnace !is CraftFurnaceFurnace) return - val resultOption = smeltingRecipeCache[furnace] + val resultOption = smeltingRecipeCache[smelted] if (resultOption.isEmpty) { sleepWithStatus(text("Invalid Recipe", RED), 250) @@ -137,18 +145,19 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu } companion object { - val smeltingRecipeCache: LoadingCache> = CacheBuilder.newBuilder().build( - CacheLoader.from { furnace -> - requireNotNull(furnace) - val furnaceTile = furnace.tileEntity - + val smeltingRecipeCache: LoadingCache> = CacheBuilder.newBuilder().build( + CacheLoader.from { itemStack -> + requireNotNull(itemStack) + val nms = CraftItemStack.asNMSCopy(itemStack) val level = Bukkit.getWorlds().first().minecraft + val input = SingleRecipeInput(nms) + // Get results for the recipe MinecraftServer.getServer().recipeManager - .getRecipeFor(RecipeType.SMELTING, furnaceTile, level) + .getRecipeFor(RecipeType.SMELTING, input, level) .map { - val b = it.value.assemble(furnaceTile, level.registryAccess()) + val b = it.value.assemble(input, level.registryAccess()) CraftItemStack.asBukkitCopy(b) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretBaseMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretBaseMultiblock.kt index aee5ec3ebc..9b04acca59 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretBaseMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretBaseMultiblock.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret +package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.SubsystemMultiblock +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.CustomTurretSubsystem -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.block.BlockFace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt index 9bef0f3b56..62842e3680 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/util/asyncTileEntities.kt @@ -1,7 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.util -import net.minecraft.world.level.block.state.BlockState as NMSBlockState -import org.bukkit.block.BlockState as BukkitBlockState import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache @@ -10,17 +8,19 @@ import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.core.BlockPos import net.minecraft.server.level.ServerLevel import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.state.BlockState as NMSBlockState import net.minecraft.world.level.chunk.LevelChunk import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.BlockState as BukkitBlockState import org.bukkit.block.data.BlockData -import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlock -import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockState -import org.bukkit.craftbukkit.v1_20_R3.block.CraftBlockStates -import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData -import org.bukkit.craftbukkit.v1_20_R3.util.CraftMagicNumbers +import org.bukkit.craftbukkit.block.CraftBlock +import org.bukkit.craftbukkit.block.CraftBlockState +import org.bukkit.craftbukkit.block.CraftBlockStates +import org.bukkit.craftbukkit.block.data.CraftBlockData +import org.bukkit.craftbukkit.util.CraftMagicNumbers import java.lang.reflect.Method fun getNMSTileEntity(block: Block, loadChunks: Boolean): BlockEntity? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSolarSiegeZone.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSolarSiegeZone.kt index d53c921f9a..c375e8a4ba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSolarSiegeZone.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/region/types/RegionSolarSiegeZone.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.common.database.string import net.horizonsend.ion.common.utils.miscellaneous.d import net.horizonsend.ion.server.features.cache.PlayerCache import net.horizonsend.ion.server.features.nations.NationsMap -import net.horizonsend.ion.server.miscellaneous.utils.distanceSquared +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import org.bukkit.entity.Player class RegionSolarSiegeZone(station: SolarSiegeZone) : Region(station), RegionTopLevel { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSiege.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSiege.kt index 59228ce264..d3e4a4a033 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSiege.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSiege.kt @@ -15,9 +15,9 @@ import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.common.utils.text.template import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.cache.PlayerCache +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.nations.region.types.RegionSolarSiegeZone import net.horizonsend.ion.server.features.nations.sieges.SolarSieges.config -import net.horizonsend.ion.server.miscellaneous.utils.Discord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.runnable diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSieges.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSieges.kt index d5f12b0813..f226495d98 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSieges.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/nations/sieges/SolarSieges.kt @@ -20,13 +20,13 @@ import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.cache.PlayerCache +import net.horizonsend.ion.server.features.chat.Discord import net.horizonsend.ion.server.features.nations.region.Regions import net.horizonsend.ion.server.features.nations.region.types.RegionSolarSiegeZone import net.horizonsend.ion.server.features.starship.active.ActiveStarships import net.horizonsend.ion.server.features.starship.control.controllers.player.PlayerController import net.horizonsend.ion.server.features.starship.damager.PlayerDamager import net.horizonsend.ion.server.features.starship.event.StarshipSunkEvent -import net.horizonsend.ion.server.miscellaneous.utils.Discord import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/progression/achievements/Achievement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/progression/achievements/Achievement.kt index a71563005f..0f1e6dd566 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/progression/achievements/Achievement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/progression/achievements/Achievement.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.progression.achievements -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.kyori.adventure.key.Key enum class Achievement( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt index 94e2794b8f..f95fd319c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/Space.kt @@ -15,6 +15,8 @@ import net.horizonsend.ion.server.features.space.body.CachedStar import net.horizonsend.ion.server.features.space.body.planet.CachedOrbitingPlanet import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet import net.horizonsend.ion.server.features.space.body.planet.CachedRoguePlanet +import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion +import net.horizonsend.ion.server.features.world.WorldFlag import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.isWater @@ -237,7 +239,6 @@ object Space : IonServerComponent() { databaseId = starId, name = starName, spaceWorldName = spaceWorldName, - spaceWorldName = spaceWorldName, location = Vec3i(starX, starY, starZ), size = starSize, seed = starSeed, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedMoon.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedMoon.kt index fb8972abec..e53edb34a7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedMoon.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/CachedMoon.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.common.database.schema.space.Moon import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.space.body.OrbitingCelestialBody.Companion.calculateOrbitLocation import net.horizonsend.ion.server.features.space.body.planet.CachedPlanet -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/OrbitingCelestialBody.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/OrbitingCelestialBody.kt index a3f40103b3..58e64a6d63 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/OrbitingCelestialBody.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/OrbitingCelestialBody.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.space.body import net.horizonsend.ion.common.utils.miscellaneous.d import net.horizonsend.ion.common.utils.miscellaneous.i -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import kotlin.math.cos import kotlin.math.sin diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedOrbitingPlanet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedOrbitingPlanet.kt index af45f0fd71..b870f51add 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedOrbitingPlanet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedOrbitingPlanet.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.space.body.CachedStar import net.horizonsend.ion.server.features.space.body.OrbitingCelestialBody import net.horizonsend.ion.server.features.space.body.OrbitingCelestialBody.Companion.calculateOrbitLocation -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedPlanet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedPlanet.kt index e57425f442..26211f9db3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedPlanet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedPlanet.kt @@ -7,8 +7,8 @@ import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.space.body.CelestialBody import net.horizonsend.ion.server.features.space.body.EnterableCelestialBody import net.horizonsend.ion.server.features.space.body.NamedCelestialBody -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.getSphereBlocks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks import net.horizonsend.ion.server.miscellaneous.utils.nms import net.kyori.adventure.text.Component import net.minecraft.world.level.block.Blocks diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedRoguePlanet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedRoguePlanet.kt index 1c41ab2875..7d9fe9ffd5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedRoguePlanet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/space/body/planet/CachedRoguePlanet.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.space.body.planet import net.horizonsend.ion.common.database.Oid import net.horizonsend.ion.common.database.schema.space.RoguePlanet import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipComputers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipComputers.kt index b92611fb8b..282ff8c069 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipComputers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/StarshipComputers.kt @@ -26,8 +26,8 @@ import net.horizonsend.ion.server.features.starship.control.movement.PlayerStars import net.horizonsend.ion.server.features.starship.event.StarshipComputerOpenMenuEvent import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.bukkitWorld +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.isPilot import net.horizonsend.ion.server.miscellaneous.utils.slPlayerId import net.kyori.adventure.text.Component.text diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt index 0d9c2d77c7..195d66ea28 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/SubsystemDetector.kt @@ -24,7 +24,7 @@ import net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive.H import net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers.MiningLaserMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer.NavigationComputerMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretBaseMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TurretBaseMultiblock import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem import net.horizonsend.ion.server.features.starship.subsystem.checklist.BargeReactorSubsystem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/player/ActivePlayerController.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/player/ActivePlayerController.kt index 434b6a0edc..1a595debbd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/player/ActivePlayerController.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/controllers/player/ActivePlayerController.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.features.starship.control.movement.PlayerStars import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.player.PlayerItemHeldEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/DirecterControlHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/DirecterControlHandler.kt index daac8da956..5fc648cf2c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/DirecterControlHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/DirecterControlHandler.kt @@ -5,8 +5,8 @@ import net.horizonsend.ion.server.features.starship.StarshipType import net.horizonsend.ion.server.features.starship.control.controllers.player.PlayerController import net.horizonsend.ion.server.features.starship.control.movement.StarshipControl import net.horizonsend.ion.server.features.starship.movement.TranslateMovement -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.vectorToBlockFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import org.bukkit.event.player.PlayerMoveEvent import org.bukkit.event.player.PlayerToggleSneakEvent import kotlin.math.roundToInt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/ShiftFlightHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/ShiftFlightHandler.kt index 6b22f20552..309f979d8c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/ShiftFlightHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/control/input/ShiftFlightHandler.kt @@ -8,7 +8,7 @@ import net.horizonsend.ion.server.features.starship.control.movement.StarshipCon import net.horizonsend.ion.server.features.starship.hyperspace.Hyperspace import net.horizonsend.ion.server.features.starship.movement.StarshipMovementException import net.horizonsend.ion.server.features.starship.movement.TranslateMovement -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.isTankPassable import org.bukkit.event.player.PlayerToggleSneakEvent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/CustomTurretSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/CustomTurretSubsystem.kt index 717f61cd93..af13faa13a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/CustomTurretSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/weapon/secondary/CustomTurretSubsystem.kt @@ -4,17 +4,17 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.modular.BlockDisplayWrapper import net.horizonsend.ion.server.features.client.display.modular.MultiBlockDisplay -import net.horizonsend.ion.server.features.multiblock.type.starshipweapon.turret.TurretBaseMultiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.turret.TurretBaseMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.starship.subsystem.DirectionalSubsystem import net.horizonsend.ion.server.features.starship.subsystem.StarshipSubsystem import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toChunkLocal import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.toChunkLocal import net.minecraft.core.BlockPos import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket import net.minecraft.network.protocol.game.ClientboundGameEventPacket diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index c05e6b6561..3d810a9ab0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport -import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.starship.event.build.StarshipBreakBlockEvent import net.horizonsend.ion.server.features.starship.event.build.StarshipPlaceBlockEvent import net.horizonsend.ion.server.features.transport.manager.TransportManager @@ -34,7 +34,7 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t override fun onEnable() { executor = Executors.newFixedThreadPool(64, Tasks.namedThreadFactory("wire-transport")) - val interval: Long = IonServer.transportSettings.extractorConfiguration.extractorTickIntervalMS + val interval: Long = ConfigurationFiles.transportSettings().extractorConfiguration.extractorTickIntervalMS monitorThread = fixedRateTimer(name = "Extractor Tick", daemon = true, initialDelay = interval, period = interval) { transportManagers.forEach { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt index 4176580622..b11ba39433 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItems.customItem +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.misc.Wrench import net.horizonsend.ion.server.features.transport.filters.FilterBlock.Companion.FILTER_STATE_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt index b58f1ad42d..00c432a412 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItems +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.misc.TransportFilterItem import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.util.CacheType @@ -22,7 +22,7 @@ object FilterBlocks : IonServerComponent() { return filters[identifier] } - val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItems.FLUID_FILTER } + val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItemRegistry.FLUID_FILTER } private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { val data = FilterBlock(identifier, cacheType, customItemSupplier) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index 86120e1c4e..e2a1378c7f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.manager.extractors -import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -32,7 +32,7 @@ abstract class ExtractorManager { private fun getDelta(time: Long): Double { val diff = time - lastTicked - return (diff.toDouble() / IonServer.transportSettings.extractorConfiguration.extractorTickIntervalMS.toDouble()) + return (diff.toDouble() / transportSettings().extractorConfiguration.extractorTickIntervalMS.toDouble()) } fun markTicked(): Double { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 221f88a42f..3e1b1c61f6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.filters.FilterBlocks @@ -26,7 +26,7 @@ import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.block.BlockFace -import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftLightningRod +import org.bukkit.craftbukkit.block.impl.CraftLightningRod import kotlin.math.roundToInt class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { @@ -63,7 +63,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa if (destinations.isEmpty()) return@submit - val transferLimit = (IonServer.transportSettings.extractorConfiguration.maxFluidRemovedPerExtractorTick * delta).roundToInt() + val transferLimit = (transportSettings().extractorConfiguration.maxFluidRemovedPerExtractorTick * delta).roundToInt() val resources = source.getExtractableResources() for ((storage, avail) in resources) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index b7d4961b21..dc986806c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder @@ -25,7 +25,7 @@ import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE import org.bukkit.block.BlockFace import org.bukkit.block.data.type.Observer -import org.bukkit.craftbukkit.v1_20_R3.block.impl.CraftEndRod +import org.bukkit.craftbukkit.block.impl.CraftEndRod import kotlin.math.roundToInt class PowerTransportCache(holder: CacheHolder) : TransportCache(holder) { @@ -60,7 +60,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC if (destinations.isEmpty()) return@submit - val transferLimit = (IonServer.transportSettings.powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() + val transferLimit = (transportSettings().powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() val transferred = minOf(source.powerStorage.getPower(), transferLimit) // Store this just in case @@ -73,7 +73,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC location, BlockFace.SELF ), - destinations.take(IonServer.transportSettings.powerConfiguration.maxExtractorDestinations), + destinations.take(transportSettings().powerConfiguration.maxExtractorDestinations), (transferred - missing) ) @@ -100,7 +100,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC location, BlockFace.SELF ), - destinations.take(IonServer.transportSettings.powerConfiguration.maxSolarDestinations), + destinations.take(transportSettings().powerConfiguration.maxSolarDestinations), transportPower ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt index 7909b85bb7..525976b3b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel -import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.NodeCacheFactory import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache @@ -56,7 +56,7 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol val data = getBlockDataSafe(world, getX(detectorPosition), getY(detectorPosition), getZ(detectorPosition)) as? DaylightDetector ?: return 0 val powerRatio = data.power.toDouble() / data.maximumPower.toDouble() - val base = IonServer.transportSettings.powerConfiguration.solarPanelTickPower * delta + val base = transportSettings().powerConfiguration.solarPanelTickPower * delta return (base * powerRatio * powerMultiplier).roundToInt() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt index 5d1d4b8791..521562a8af 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.transport.util import com.fastasyncworldedit.core.history.changeset.AbstractChangeSet -import com.sk89q.jnbt.CompoundTag +import com.fastasyncworldedit.core.history.changeset.ChangeExchangeCoordinator +import com.fastasyncworldedit.core.nbt.FaweCompoundTag import com.sk89q.worldedit.bukkit.BukkitAdapter +import com.sk89q.worldedit.extent.inventory.BlockBag import com.sk89q.worldedit.history.change.Change import com.sk89q.worldedit.world.World import com.sk89q.worldedit.world.biome.BiomeType @@ -30,6 +32,11 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { } } + override fun addTileCreate(tag: FaweCompoundTag?) {} + override fun addTileRemove(tag: FaweCompoundTag?) {} + override fun addEntityRemove(tag: FaweCompoundTag?) {} + override fun addEntityCreate(tag: FaweCompoundTag?) {} + private fun processMultiblock(x: Int, y: Int, z: Int) { Tasks.sync { val state = bukkitWorld.getBlockState(x, y, z) as? Sign ?: return@sync @@ -55,11 +62,15 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { return counter } - override fun addTileCreate(tag: CompoundTag?) {} - override fun addTileRemove(tag: CompoundTag?) {} - override fun addEntityRemove(tag: CompoundTag?) {} - override fun addEntityCreate(tag: CompoundTag?) {} override fun addBiomeChange(x: Int, y: Int, z: Int, from: BiomeType?, to: BiomeType?) {} + override fun getCoordinatedChanges( + blockBag: BlockBag?, + mode: Int, + dir: Boolean, + ): ChangeExchangeCoordinator? { + TODO("Not yet implemented") + } + override fun getIterator(redo: Boolean): MutableIterator { return Collections.emptyIterator() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index c242db750a..9ff9ffdd2d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -189,7 +189,7 @@ class IonChunk(val inner: Chunk) { } /** Mark this chunk as needing to be saved */ - fun markUnsaved() { inner.minecraft.isUnsaved = true } + fun markUnsaved() { inner.minecraft.markUnsaved() } fun isInBounds(x: Int, y: Int, z: Int): Boolean { if (!(0..15).contains(x - originX)) return false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BatteryListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BatteryListener.kt deleted file mode 100644 index c7353a83bc..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/BatteryListener.kt +++ /dev/null @@ -1,47 +0,0 @@ -package net.horizonsend.ion.server.listener.misc - -import net.horizonsend.ion.server.features.gear.getPower -import net.horizonsend.ion.server.features.gear.setPower -import net.horizonsend.ion.server.features.multiblock.MultiblockAccess -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.registrations.legacy.CustomItems -import org.bukkit.block.Sign -import org.bukkit.event.EventHandler -import org.bukkit.event.player.PlayerInteractEvent - -object BatteryListener : SLEventListener() { - @EventHandler - fun onPlayerInteract(event: PlayerInteractEvent) { - val sign = event.clickedBlock?.state as? Sign ?: return - val multiblock = MultiblockAccess.getFast(sign) ?: return - if (multiblock !is EntityMultiblock<*>) return - - val entity = multiblock.getMultiblockEntity(sign) ?: return - if (entity !is PoweredMultiblockEntity) return - - val item = event.item ?: return - if (CustomItems[item] !is CustomItems.BatteryItem) return - - handleBatteryInput(entity, event) - } - - private fun handleBatteryInput(entity: PoweredMultiblockEntity, event: PlayerInteractEvent) { - val item = event.item ?: return - - val power = getPower(item) - var powerToTransfer = power * item.amount - if (powerToTransfer == 0) return - - val machinePower = entity.powerStorage.getPower() - val maxMachinePower = entity.powerStorage.capacity - - if (maxMachinePower - machinePower < powerToTransfer) { - powerToTransfer = maxMachinePower - machinePower - } - - setPower(item, power - powerToTransfer / item.amount) - entity.powerStorage.addPower(powerToTransfer) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt index c170f33d00..39c47042aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/ProtectionListener.kt @@ -24,6 +24,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.action import net.horizonsend.ion.server.miscellaneous.utils.colorize import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distance import net.horizonsend.ion.server.miscellaneous.utils.isPilot import net.horizonsend.ion.server.miscellaneous.utils.msg import org.bukkit.Location @@ -201,14 +202,13 @@ object ProtectionListener : SLEventListener() { } fun isPlanetOrbitDenied(player: Player, location: Location, silent: Boolean): Boolean { - val (world, x, y, z) = location val padding = 500 var inOwnStation = false - for (planet in Space.getOrbitingPlanets().filter { it.spaceWorld == world }) { + for (planet in Space.getOrbitingPlanets().filter { it.spaceWorld == location.world }) { val minDistance = planet.orbitDistance - padding val maxDistance = planet.orbitDistance + padding - val distance = distance(x.toInt(), y.toInt(), z.toInt(), planet.sun.location.x, y.toInt(), planet.sun.location.z).toInt() + val distance = distance(location.blockX, location.blockY, location.blockZ, planet.sun.location.x, location.blockY, planet.sun.location.z).toInt() // Within planet orbit if (distance in minDistance..maxDistance) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt index 5e963065a3..f647652dbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt @@ -125,6 +125,7 @@ import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.custom.items.type.armor.PowerArmorItem import net.horizonsend.ion.server.features.custom.items.type.tool.Battery import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ModificationItem +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.TERRACOTTA_TYPES import net.horizonsend.ion.server.miscellaneous.utils.WOOL_TYPES import net.horizonsend.ion.server.miscellaneous.utils.updateData @@ -142,7 +143,6 @@ import org.bukkit.Material.COMPOSTER import org.bukkit.Material.COPPER_BLOCK import org.bukkit.Material.COPPER_INGOT import org.bukkit.Material.CRAFTING_TABLE -import org.bukkit.Material.CYAN_WOOL import org.bukkit.Material.DARK_PRISMARINE import org.bukkit.Material.DIAMOND import org.bukkit.Material.DIAMOND_BLOCK @@ -611,7 +611,7 @@ object Crafting : IonServerComponent() { setIngredient('z', FUEL_CONTROL.constructItemStack()) } - itemStackShapeRecipe("multiblock_workbench", MULTIBLOCK_WORKBENCH.constructItemStack()) { + shaped("multiblock_workbench", MULTIBLOCK_WORKBENCH.constructItemStack()) { shape("i", "c") setIngredient('i', IRON_BLOCK) @@ -619,7 +619,7 @@ object Crafting : IonServerComponent() { } // Tool Mods start - itemStackShapeRecipe("silk_touch_modifier", SILK_TOUCH_MOD.constructItemStack()) { + shaped("silk_touch_modifier", SILK_TOUCH_MOD.constructItemStack()) { shape("gbg", "tst", "ctc") setIngredient('g', RAW_GOLD) @@ -628,6 +628,7 @@ object Crafting : IonServerComponent() { setIngredient('s', ItemStack(ENCHANTED_BOOK).updateData(DataComponentTypes.ENCHANTMENTS, ItemEnchantments.itemEnchantments(mutableMapOf(Enchantment.SILK_TOUCH to 1), true))) setIngredient('c', CIRCUIT_BOARD.constructItemStack()) } + shaped("fortune_1_touch_modifier", FORTUNE_1.constructItemStack()) { shape("dgd", "csc", "dgd") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt index 12f6489b66..a8d3818ae0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Listeners.kt @@ -5,8 +5,9 @@ import net.horizonsend.ion.server.features.client.networking.packets.WorldPacket import net.horizonsend.ion.server.features.custom.blocks.CustomBlockListeners import net.horizonsend.ion.server.features.custom.items.CustomItemListeners import net.horizonsend.ion.server.features.custom.items.type.PersonalTransporterManager -import net.horizonsend.ion.server.features.custom.items.mods.ToolModMenu -import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListenersb +import net.horizonsend.ion.server.features.custom.items.type.tool.mods.ToolModMenu +import net.horizonsend.ion.server.features.custom.items.type.weapon.blaster.BlasterListeners +import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.type.misc.AbstractTractorBeam @@ -41,8 +42,6 @@ import net.horizonsend.ion.server.listener.nations.MovementListener import org.bukkit.event.Listener val listeners: List = listOf( - IonWorld, - // StarLegacy JoinLeaveListener, MovementListener, @@ -79,10 +78,9 @@ val listeners: List = listOf( AbstractTractorBeam.Companion, PlayerDeathListener, ToolModMenu, - InteractableGUI, + InteractableGUI.Companion, RecipeModifications, ActivePlayerController.Companion, - TransportManager, PersonalTransporterManager, MultiblockEntities, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt index 82622cb54e..bcc5bd5e4a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt @@ -4,7 +4,7 @@ import io.papermc.paper.datacomponent.DataComponentType import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.utils.text.BOLD import net.horizonsend.ion.common.utils.text.plainText -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.kyori.adventure.key.Key From 97e02687773b25ab7fa6285b269cfa17de2037f6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 29 Dec 2024 21:44:59 -0600 Subject: [PATCH 371/500] Fix up wrench, workbench --- .../custom/items/CustomItemRegistry.kt | 6 +++--- .../features/custom/items/misc/Wrench.kt | 21 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index ae3646c72e..2aa9b37e4a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -325,13 +325,13 @@ object CustomItemRegistry : IonServerComponent() { val PACKAGED_MULTIBLOCK = register(PackagedMultiblock) val MULTIBLOCK_WORKBENCH = register(CustomBlockItem( identifier = "MULTIBLOCK_WORKBENCH", - displayName = text("Multiblock Workbench").itemName, - customModel = "misc/multiblock_workbench" + displayName = text("Multiblock Workbench"), + customModel = "tool/multiblock_workbench" ) { CustomBlocks.MULTIBLOCK_WORKBENCH }) val WRENCH = register(Wrench) - val FLUID_FILTER: TransportFilterItem = register(TransportFilterItem("FLUID_FILTER", text("Fluid Filter").itemName) { FilterBlocks.FLUID_FILTER }) + val FLUID_FILTER: TransportFilterItem = register(TransportFilterItem("FLUID_FILTER", text("Fluid Filter")) { FilterBlocks.FLUID_FILTER }) private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( text("$tierName ", tierColor), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index f2b572ee46..5495e11edd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -13,27 +13,27 @@ import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import net.kyori.adventure.text.Component.text import org.bukkit.block.Sign -import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent object Wrench : CustomItem( "WRENCH", text("Wrench"), - ItemFactory.unStackableCustomItem + ItemFactory.builder(ItemFactory.unStackableCustomItem) + .setCustomModel("tool/wrench") + .build() ) { override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@Wrench) { event, _, itemStack -> handleSecondaryInteract(event.player, event) }) + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@Wrench) { event, _, itemStack -> - handlePrimaryInteract(event.player, event) + checkStructure(event.player, event) }) } - private fun handlePrimaryInteract(livingEntity: LivingEntity, event: PlayerInteractEvent) { - if (livingEntity !is Player) return - + private fun checkStructure(player: Player, event: PlayerInteractEvent) { val hitBlock = event.clickedBlock if (hitBlock?.type?.isWallSign != true) return @@ -41,19 +41,18 @@ object Wrench : CustomItem( val multiblock = MultiblockAccess.getFast(sign) ?: return if (multiblock.signMatchesStructure(sign, loadChunks = false, particles = false)) { - livingEntity.information("Multiblock structure is correct.") + player.information("Multiblock structure is correct.") return } - MultiblockCommand.onCheck(livingEntity, multiblock, sign.x, sign.y, sign.z) + MultiblockCommand.onCheck(player, multiblock, sign.x, sign.y, sign.z) } - private fun handleSecondaryInteract(livingEntity: LivingEntity, event: PlayerInteractEvent?) { - if (livingEntity !is Player) return + private fun handleSecondaryInteract(player: Player, event: PlayerInteractEvent?) { val clickedBlock = event?.clickedBlock ?: return val state = clickedBlock.state - if (livingEntity.isSneaking && state is Sign) return tryPickUpMultiblock(livingEntity, state) + if (player.isSneaking && state is Sign) return tryPickUpMultiblock(player, state) } private fun tryPickUpMultiblock(player: Player, sign: Sign) { From 665ecfd32504b17be4ee41abf7df8fb5412d8c07 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 29 Dec 2024 22:50:08 -0600 Subject: [PATCH 372/500] fix comodification error, initialization order problem --- .../features/custom/blocks/MultiblockWorkbench.kt | 8 +++++--- .../server/features/multiblock/MultiblockEntities.kt | 11 ++++++----- .../server/features/multiblock/MultiblockTicking.kt | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index ddb83b82ae..7700b14912 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -24,7 +24,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updateLore import net.horizonsend.ion.server.miscellaneous.utils.updateMeta -import net.kyori.adventure.text.Component.empty import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GRAY import net.kyori.adventure.text.format.NamedTextColor.GREEN @@ -53,7 +52,8 @@ object MultiblockWorkbench : InteractableCustomBlock( ) { private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) - val multiblocks = MultiblockRegistration.getAllMultiblocks().toList() + // Initalized before multiblocks are registered + val multiblocks by lazy { MultiblockRegistration.getAllMultiblocks().toList() } private var multiblockIndex = 0 private val currentMultiblock get() = multiblocks[multiblockIndex] @@ -114,6 +114,8 @@ object MultiblockWorkbench : InteractableCustomBlock( } private fun setGuiOverlay(view: InventoryView) { + println(multiblocks.size) + val text = GuiText("Multiblock Workbench") .setSlotOverlay( "# # # # # # # # #", @@ -217,7 +219,7 @@ object MultiblockWorkbench : InteractableCustomBlock( TextInputMenu( player, text("Search by Multiblock Name"), - empty(), + text("Top result is selected"), backButtonHandler = { this.open() isSearching = false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index 8d6200ebe9..d4c0f938e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -1,7 +1,5 @@ package net.horizonsend.ion.server.features.multiblock -import org.bukkit.block.Sign as SignState -import org.bukkit.block.data.type.WallSign as SignData import com.destroystokyo.paper.event.server.ServerTickEndEvent import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -20,6 +18,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.World import org.bukkit.block.Block +import org.bukkit.block.Sign as SignState +import org.bukkit.block.data.type.WallSign as SignData import org.bukkit.event.EventHandler /** @@ -135,15 +135,16 @@ object MultiblockEntities : SLEventListener() { fun onTickEnd(event: ServerTickEndEvent) { if (event.timeRemaining < 0) return - val sorted = MultiblockTicking.getAllMultiblockManagers() - for (manager in sorted) { - if (manager.getSignUnsavedTime() < 5000L) continue + MultiblockTicking.iterateManagers { manager -> + if (manager.getSignUnsavedTime() < 5000L) return@iterateManagers for (keyEntity in manager.getAllMultiblockEntities()) { if (event.timeRemaining < 0) return keyEntity.value.saveToSign() } + manager.markSignSaved() } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt index baf80560cc..3f1093b344 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockTicking.kt @@ -49,9 +49,9 @@ object MultiblockTicking : IonServerComponent() { } } - fun iterateManagers(task: (MultiblockManager) -> Unit) { + inline fun iterateManagers(task: (MultiblockManager) -> Unit) { @Suppress("UNCHECKED_CAST") - val clone = managers.clone() as ArrayList + val clone = getAllMultiblockManagers().clone() as ArrayList clone.forEach(task) } From c146273999d1bcd994182b94bba69d96ddd34361 Mon Sep 17 00:00:00 2001 From: diena1dev Date: Tue, 31 Dec 2024 01:20:36 -0600 Subject: [PATCH 373/500] fix for custom turret rendering (temporary) --- .../features/client/display/modular/BlockDisplayWrapper.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/BlockDisplayWrapper.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/BlockDisplayWrapper.kt index 9c60d90f40..c3ec00f799 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/BlockDisplayWrapper.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/BlockDisplayWrapper.kt @@ -69,6 +69,7 @@ class BlockDisplayWrapper( teleportDuration = 1 interpolationDuration = 1 viewRange = 1000f + brightness = org.bukkit.entity.Display.Brightness(15, 15) transformation = Transformation( offset.toVector3f(), From e72c41cef212366ae2a301ecd576a3e82bbeeff7 Mon Sep 17 00:00:00 2001 From: diena1dev Date: Tue, 31 Dec 2024 01:48:40 -0600 Subject: [PATCH 374/500] added BLACK_ENERGY_SWORD recipe --- .../ion/server/miscellaneous/registrations/Crafting.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt index f647652dbc..5867e1bf24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt @@ -41,6 +41,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERG import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_PURPLE import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_RED import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_YELLOW +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_BLACK import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENRICHED_URANIUM import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.EXTENDED_BAR @@ -205,6 +206,7 @@ import org.bukkit.Material.STRING import org.bukkit.Material.TRIPWIRE_HOOK import org.bukkit.Material.TURTLE_EGG import org.bukkit.Material.VERDANT_FROGLIGHT +import org.bukkit.Material.WITHER_ROSE import org.bukkit.NamespacedKey import org.bukkit.enchantments.Enchantment import org.bukkit.inventory.FurnaceRecipe @@ -790,6 +792,7 @@ object Crafting : IonServerComponent() { registerSwordRecipes(ENERGY_SWORD_PURPLE, ExactChoice(CHETHERITE.constructItemStack())) registerSwordRecipes(ENERGY_SWORD_ORANGE, RecipeChoice.MaterialChoice(COPPER_INGOT)) registerSwordRecipes(ENERGY_SWORD_PINK, RecipeChoice.MaterialChoice(PINK_TULIP)) + registerSwordRecipes(ENERGY_SWORD_BLACK, RecipeChoice.MaterialChoice(WITHER_ROSE)) } // Different names due to signature problems from type erasure From 1593179765cb00fabf370537f8cdd69004c1ab84 Mon Sep 17 00:00:00 2001 From: diena1dev Date: Wed, 1 Jan 2025 00:50:30 -0600 Subject: [PATCH 375/500] removed BLACK_ENERGY_SWORD recipe and corresponding imports --- .../ion/server/miscellaneous/registrations/Crafting.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt index 5867e1bf24..f647652dbc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Crafting.kt @@ -41,7 +41,6 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERG import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_PURPLE import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_RED import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_YELLOW -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENERGY_SWORD_BLACK import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENRICHED_URANIUM import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.ENRICHED_URANIUM_BLOCK import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.EXTENDED_BAR @@ -206,7 +205,6 @@ import org.bukkit.Material.STRING import org.bukkit.Material.TRIPWIRE_HOOK import org.bukkit.Material.TURTLE_EGG import org.bukkit.Material.VERDANT_FROGLIGHT -import org.bukkit.Material.WITHER_ROSE import org.bukkit.NamespacedKey import org.bukkit.enchantments.Enchantment import org.bukkit.inventory.FurnaceRecipe @@ -792,7 +790,6 @@ object Crafting : IonServerComponent() { registerSwordRecipes(ENERGY_SWORD_PURPLE, ExactChoice(CHETHERITE.constructItemStack())) registerSwordRecipes(ENERGY_SWORD_ORANGE, RecipeChoice.MaterialChoice(COPPER_INGOT)) registerSwordRecipes(ENERGY_SWORD_PINK, RecipeChoice.MaterialChoice(PINK_TULIP)) - registerSwordRecipes(ENERGY_SWORD_BLACK, RecipeChoice.MaterialChoice(WITHER_ROSE)) } // Different names due to signature problems from type erasure From 1b6e6898bfde090a82f315a808c0cc1e94dc3a03 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 29 Dec 2024 22:54:25 -0600 Subject: [PATCH 376/500] Sign text util to avoid raw arrays --- .../ion/server/features/multiblock/Multiblock.kt | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt index 827bff51d2..7420db8e18 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/Multiblock.kt @@ -2,8 +2,8 @@ package net.horizonsend.ion.server.features.multiblock import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isValidYLevel +import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.kyori.adventure.text.Component @@ -91,7 +91,7 @@ abstract class Multiblock { for (i in 0..3) { val text = signText[i] if (text != null) { - sign.line(i, text) + sign.front().line(i, text) } } @@ -110,13 +110,9 @@ abstract class Multiblock { ) } - protected open fun onTransformSign(player: Player, sign: Sign) {} - - companion object { - fun getOrigin(sign: Sign): Vec3i { - val face = sign.getFacing() - - return Vec3i(sign.location).minus(Vec3i(face.modX, 0, face.modZ)) - } + protected fun createSignText(line1: Component?, line2: Component?, line3: Component?, line4: Component?): Array { + return arrayOf(line1, line2, line3, line4) } + + protected open fun onTransformSign(player: Player, sign: Sign) {} } From 0559097f8c1d401be2332f9725265e86711f4d99 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 30 Dec 2024 12:42:13 -0600 Subject: [PATCH 377/500] work on fixes --- .../custom/blocks/MultiblockWorkbench.kt | 1 + .../custom/items/misc/PackagedMultiblock.kt | 9 ++++----- .../server/features/multiblock/PrePackaged.kt | 20 +++++++++---------- .../multiblock/type/DisplayNameMultilblock.kt | 19 ++++++++++++++++++ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 7700b14912..8e248a2ffe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -61,6 +61,7 @@ object MultiblockWorkbench : InteractableCustomBlock( val player = event.player event.isCancelled = true + // Prevent the double firing of player interact events cooldown.tryExec(player) { openMenu(player, block.location.toCenterLocation()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index 967b479737..dfef164c64 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.custom.items.misc +import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.ofChildren @@ -20,12 +21,10 @@ import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.block.Chest import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.BlockStateMeta import java.util.Locale object PackagedMultiblock : CustomItem( @@ -63,7 +62,7 @@ object PackagedMultiblock : CustomItem( return } - val inventory = ((itemStack.itemMeta as? BlockStateMeta)?.blockState as? Chest)?.inventory ?: return livingEntity.userError("The packaged multiblock has no data!") + val contents = itemStack.getData(DataComponentTypes.CONTAINER) ?: return livingEntity.userError("The packaged multiblock has no data!") val direction = livingEntity.facing val origin = PrePackaged.getOriginFromPlacement( @@ -82,14 +81,14 @@ object PackagedMultiblock : CustomItem( val entityData = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) - runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, inventory, entityData) }.onFailure { + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, contents.contents(), entityData) }.onFailure { livingEntity.information("ERROR: $it") it.printStackTrace() }.onSuccess { // Drop remaining items in packaged multi val dropLocation = origin.getRelative(direction.oppositeFace).location.toCenterLocation() - for (item in inventory.contents.filterNotNull()) { + for (item in contents.contents().filterNotNull()) { livingEntity.world.dropItem(dropLocation, item) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index c12d59b18d..d3e40761fd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.multiblock +import io.papermc.paper.datacomponent.DataComponentTypes +import io.papermc.paper.datacomponent.item.ItemContainerContents import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock import net.horizonsend.ion.server.features.multiblock.MultiblockEntities.loadFromData @@ -21,6 +23,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isSign import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updateMeta import net.kyori.adventure.text.Component.text import org.bukkit.Material @@ -85,7 +88,7 @@ object PrePackaged { return obstructed } - fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock, itemSource: Inventory?, entityData: PersistentMultiblockData?) { + fun place(player: Player, origin: Block, direction: BlockFace, multiblock: Multiblock, itemSource: List?, entityData: PersistentMultiblockData?) { val requirements = multiblock.shape.getRequirementMap(direction) val placements = mutableMapOf() @@ -102,7 +105,6 @@ object PrePackaged { if (itemSource != null) { itemSource - .filterNotNull() .firstOrNull { requirement.itemRequirement.itemCheck(it) } ?.let { usedItem = it.clone() @@ -125,7 +127,7 @@ object PrePackaged { val placement = if (usedItem == null) { requirement.example.clone() } else { - requirement.itemRequirement.toBlock.invoke(usedItem!!) + requirement.itemRequirement.toBlock.invoke(usedItem) } requirement.executePlacementModifications(placement, direction) @@ -140,7 +142,7 @@ object PrePackaged { } if (multiblock is SignlessStarshipWeaponMultiblock<*>) return - val signItem: ItemStack? = itemSource?.contents?.firstOrNull { it?.type?.isSign == true } + val signItem: ItemStack? = itemSource?.firstOrNull { it.type.isSign == true } // If there is an item source but no sign then there is not one available if (itemSource != null && signItem == null) return @@ -241,15 +243,11 @@ object PrePackaged { fun createPackagedItem(availableItems: List, multiblock: Multiblock): ItemStack { val base = PackagedMultiblock.createFor(multiblock) - return base.updateMeta { - it as BlockStateMeta - @Suppress("UnstableApiUsage") - val newState = Material.CHEST.createBlockData().createBlockState() as Chest - packageFrom(availableItems, multiblock, newState.inventory) + @Suppress("UnstableApiUsage") val newState = Material.CHEST.createBlockData().createBlockState() as Chest + packageFrom(availableItems, multiblock, newState.inventory) - it.blockState = newState - } + return base.updateData(DataComponentTypes.CONTAINER, ItemContainerContents.containerContents(newState.inventory.contents.toList())) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt index f95984f661..82edd664f9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt @@ -1,13 +1,32 @@ package net.horizonsend.ion.server.features.multiblock.type import net.horizonsend.ion.common.utils.text.toComponent +import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updateLore import net.kyori.adventure.text.Component +import org.bukkit.Material +import org.bukkit.inventory.ItemStack interface DisplayNameMultilblock { val displayName: Component + val description: Component + +// val iconModel: Key companion object { fun Multiblock.getDisplayName() = if (this is DisplayNameMultilblock) displayName else javaClass.simpleName.toComponent() + + fun Multiblock.getIcon(): ItemStack { + val base = ItemStack(Material.CHEST) + .updateDisplayName(getDisplayName()) + + return if (this is DisplayNameMultilblock) base +// .updateData(DataComponentTypes.ITEM_MODEL, iconModel) + .updateLore(description.wrap(150)) + else + base + } } } From b64797530405a3f85f594b997bc34101ca1497d1 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 1 Jan 2025 22:29:53 -0600 Subject: [PATCH 378/500] disable fluid for now, fix upstream changes --- .../economy/cargotrade/ShipmentManager.kt | 2 +- .../multiblock/MultiblockRegistration.kt | 9 +++------ .../multiblock/type/drills/DrillMultiblock.kt | 2 ++ .../type/fluid/ElectrolysisMultiblock.kt | 1 + .../type/power/charger/ChargerMultiblock.kt | 1 + .../type/power/storage/PowerBankMultiblock.kt | 1 + .../type/power/storage/PowerCellMultiblock.kt | 1 + .../NavigationComputerMultiblockAdvanced.kt | 1 + .../starship/movement/StarshipMovement.kt | 1 + .../transport/manager/ChunkTransportManager.kt | 17 ++++++++--------- .../transport/manager/ShipTransportManager.kt | 9 ++++----- .../transport/manager/TransportManager.kt | 5 ++--- .../server/features/transport/util/CacheType.kt | 7 +++++-- 13 files changed, 31 insertions(+), 26 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/cargotrade/ShipmentManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/cargotrade/ShipmentManager.kt index 31bf210f29..93d9b92b32 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/cargotrade/ShipmentManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/economy/cargotrade/ShipmentManager.kt @@ -35,7 +35,7 @@ import net.horizonsend.ion.server.features.progression.achievements.rewardAchiev import net.horizonsend.ion.server.features.space.Space import net.horizonsend.ion.server.features.starship.StarshipType import net.horizonsend.ion.server.features.starship.TypeCategory -import net.horizonsend.ion.server.miscellaneous.registrations.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.MenuHelper import net.horizonsend.ion.server.miscellaneous.utils.Notify import net.horizonsend.ion.server.miscellaneous.utils.SLTextStyle diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 21ec21f6a1..72fc502ed7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -31,12 +31,9 @@ import net.horizonsend.ion.server.features.multiblock.type.farming.planter.Plant import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier2 import net.horizonsend.ion.server.features.multiblock.type.farming.planter.PlanterMultiblockTier3 import net.horizonsend.ion.server.features.multiblock.type.fluid.CanisterVentMultiblock -import net.horizonsend.ion.server.features.multiblock.type.fluid.ElectrolysisMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.GasPowerPlantMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.PipedGasCollectorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankMedium -import net.horizonsend.ion.server.features.multiblock.type.fluid.storage.FluidTankSmall import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock @@ -285,9 +282,9 @@ object MultiblockRegistration : IonServerComponent() { registerMultiblock(CanisterVentMultiblock) registerMultiblock(GasPowerPlantMultiblock) - registerMultiblock(ElectrolysisMultiblock) - registerMultiblock(FluidTankSmall) - registerMultiblock(FluidTankMedium) +// registerMultiblock(ElectrolysisMultiblock) +// registerMultiblock(FluidTankSmall) +// registerMultiblock(FluidTankMedium) // registerMultiblock(FluidTankLarge) // Defenses diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 81f2cac03b..89016469d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -49,6 +49,8 @@ import java.util.UUID import kotlin.math.max abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { + override val description: Component = text("Drills blocks in a ${javaClass.simpleName.substringBefore("Mirrored").substringAfter("DrillMultiblock").toInt() + 2} block radius") + abstract val radius: Int abstract val coolDown: Int abstract val mirrored: Boolean diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt index 8291ab6bfb..22e645c839 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/ElectrolysisMultiblock.kt @@ -54,6 +54,7 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataAdapterContext object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { + override val description: Component = text("Turns water into Hydrogen and Oxygen gas") override val name: String = "ElectrolysisMultiblock" override val alternativeDetectionNames: Array = arrayOf("Electrolysis") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt index c341d2fa8a..4e0aa78535 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/charger/ChargerMultiblock.kt @@ -29,6 +29,7 @@ import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMultiblock, FurnaceMultiblock, DisplayNameMultilblock { + override val description: Component = Component.text("Charges powered items.") protected abstract val tierMaterial: Material protected abstract val powerPerSecond: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index d9151f1548..a51fbdacf8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -23,6 +23,7 @@ import org.bukkit.event.player.PlayerInteractEvent abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val maxPower: Int + override val description: Component = Component.text("Stores $maxPower power") abstract val tierMaterial: Material override val name = "powerbank" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt index 5e1fb199af..9f93e05e33 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerCellMultiblock.kt @@ -26,6 +26,7 @@ object PowerCellMultiblock : Multiblock(), EntityMultiblock = ShipCacheHolder(this) { SolarPanelCache(it) } - override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } +// override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } init { load() @@ -26,7 +25,7 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { fun load() { powerNodeManager.capture() solarPanelManager.capture() - fluidNodeManager.capture() +// fluidNodeManager.capture() extractorManager.loadExtractors() NewTransport.registerTransportManager(this) } @@ -34,7 +33,7 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { fun release() { powerNodeManager.release() solarPanelManager.release() - fluidNodeManager.release() +// fluidNodeManager.release() extractorManager.releaseExtractors() NewTransport.removeTransportManager(this) } @@ -42,7 +41,7 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { fun displace(movement: StarshipMovement) { powerNodeManager.displace(movement) solarPanelManager.displace(movement) - fluidNodeManager.displace(movement) +// fluidNodeManager.displace(movement) extractorManager.displace(movement) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index d6c6794e44..ec992cc6af 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder -import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager @@ -11,7 +10,7 @@ abstract class TransportManager { abstract val extractorManager: ExtractorManager abstract val powerNodeManager: CacheHolder abstract val solarPanelManager: CacheHolder - abstract val fluidNodeManager: CacheHolder +// abstract val fluidNodeManager: CacheHolder abstract fun getInputProvider(): InputManager @@ -19,7 +18,7 @@ abstract class TransportManager { for (extractor in extractorManager.getExtractors()) { val delta = extractor.markTicked() powerNodeManager.cache.tickExtractor(extractor.pos, delta) - fluidNodeManager.cache.tickExtractor(extractor.pos, delta) +// fluidNodeManager.cache.tickExtractor(extractor.pos, delta) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index 5de0718a41..be4d823921 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportC import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache +import net.horizonsend.ion.server.features.transport.util.CacheType.entries import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import org.bukkit.NamespacedKey @@ -30,11 +31,13 @@ enum class CacheType(val namespacedKey: NamespacedKey) { }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { override fun get(chunk: IonChunk): FluidTransportCache { - return chunk.transportNetwork.fluidNodeManager.cache + TODO("Fluid is disabled") +// return chunk.transportNetwork.fluidNodeManager.cache } override fun get(ship: ActiveStarship): FluidTransportCache { - return ship.transportManager.fluidNodeManager.cache + TODO("Fluid is disabled") +// return ship.transportManager.fluidNodeManager.cache } }, From 978c0f71507435ddafc112efd5c5df703463b3b2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 17:17:59 -0600 Subject: [PATCH 379/500] fix number format --- .../server/features/multiblock/type/drills/DrillMultiblock.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 89016469d8..e28d0130c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -49,7 +49,7 @@ import java.util.UUID import kotlin.math.max abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { - override val description: Component = text("Drills blocks in a ${javaClass.simpleName.substringBefore("Mirrored").substringAfter("DrillMultiblock").toInt() + 2} block radius") + override val description: Component = text("Drills blocks in a ${javaClass.simpleName.substringBefore("Mirrored").substringAfter("DrillMultiblockTier").toInt() + 2} block radius") abstract val radius: Int abstract val coolDown: Int From 152f18725666069a976b49d8cdbd58f62f2d653e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 17:20:28 -0600 Subject: [PATCH 380/500] skip multiblocks that could not be deserialized --- .../multiblock/manager/ChunkMultiblockManager.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index bf78cff7e2..ae968b3884 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.manager +import kotlinx.serialization.SerializationException import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.MultiblockTicking import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -90,7 +91,13 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag } for (serializedMultiblockData in serialized) { - val stored = PersistentMultiblockData.fromPrimitive(serializedMultiblockData, chunk.inner.persistentDataContainer.adapterContext) + val stored = runCatching { + PersistentMultiblockData.fromPrimitive(serializedMultiblockData, chunk.inner.persistentDataContainer.adapterContext) + }.onFailure { exception -> + if (exception is SerializationException) { + log.warn("Could not load multiblock, skipping.") + } + }.getOrNull() ?: continue val multiblock = stored.type as EntityMultiblock<*> From 6a25f89ee83cffeb282cc1b8222e801a2b12634d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 17:28:08 -0600 Subject: [PATCH 381/500] fix build limit bug --- .../ion/server/features/multiblock/shape/MultiblockShape.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index a736075d82..6c6aee5c68 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -184,6 +184,9 @@ class MultiblockShape { val x = offset.x val y = offset.y val z = offset.z + + if ((y + origin.y) !in origin.world.minHeight ..< origin.world.maxHeight) return@all false + val relative: Block = if (loadChunks) { origin.getRelative(x, y, z) } else { From 0bc4f10a9c4f1cd67b2cf42c3b310f243bf69d26 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 17:43:36 -0600 Subject: [PATCH 382/500] fix build limit bug --- .../net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index 7deaf69b5a..895fda1ab9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -44,7 +44,7 @@ fun getBlockDataSafe(world: World, x: Int, y: Int, z: Int, loadChunks: Boolean = * Gets the block state at the given location if loaded. Sync only. */ fun getBlockIfLoaded(world: World, x: Int, y: Int, z: Int): Block? { - if (y < 0 || y > world.maxHeight) { + if (y < 0 || y >= world.maxHeight) { return null } From 2faf0cdae706a932ef5fd75b902c1c65f779038f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 18:28:20 -0600 Subject: [PATCH 383/500] update packaged multiblocks to 1.21 --- .../custom/blocks/MultiblockWorkbench.kt | 1 - .../items/component/CustomComponentTypes.kt | 5 +++ .../items/component/StoredMultiblock.kt | 34 +++++++++++++++ .../custom/items/misc/MultiblockToken.kt | 18 ++------ .../custom/items/misc/PackagedMultiblock.kt | 41 ++++++++----------- .../server/features/multiblock/PrePackaged.kt | 15 +++---- 6 files changed, 66 insertions(+), 48 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 8e248a2ffe..de30dcc606 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -89,7 +89,6 @@ object MultiblockWorkbench : InteractableCustomBlock( override fun setup(view: InventoryView) { lockedSlots.addAll(BACKGROUND_SLOTS) - addGuiButton(LEFT_BUTTON_SLOT, GuiItem.LEFT.makeItem(text("Previous Multiblock"))) { multiblockIndex = (multiblockIndex - 1).coerceAtLeast(0) refreshMultiblock(it.view) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/CustomComponentTypes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/CustomComponentTypes.kt index 11be6229c4..fd0a3e4a5e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/CustomComponentTypes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/CustomComponentTypes.kt @@ -56,6 +56,11 @@ class CustomComponentTypes> pr **/ val SMELTABLE = newComponentType>(ComponentType.ONLY_ONE) + /** + * Specifiies a result from smelting this item + **/ + val MULTIBLOCK_TYPE = newComponentType>(ComponentType.ONLY_ONE) + /** * General interact listener **/ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt new file mode 100644 index 0000000000..24c33516aa --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.custom.items.component + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.attribute.CustomItemAttribute +import net.horizonsend.ion.server.features.multiblock.PrePackaged +import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor.GRAY +import org.bukkit.inventory.ItemStack +import java.util.Locale + +object StoredMultiblock : CustomItemComponent, LoreManager { + override val priority: Int = 1 + + override fun decorateBase(baseItem: ItemStack, customItem: CustomItem) {} + + override fun getAttributes(baseItem: ItemStack): Iterable = listOf() + + override fun getLines(customItem: CustomItem, itemStack: ItemStack): List { + val multiblock = PrePackaged.getTokenData(itemStack) ?: return listOf() + return listOf( + ofChildren(text("Multiblock: ", GRAY), text(multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) })).itemLore, + ofChildren(text("Variant: ", GRAY), text(multiblock.javaClass.simpleName)).itemLore, + text("Left click to preview").itemLore, + text("Right click to place").itemLore + ) + } + + override fun shouldIncludeSeparator(): Boolean { + return false + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index fc26f5e73e..a5a7a1f7a7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -1,27 +1,21 @@ package net.horizonsend.ion.server.features.custom.items.misc import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.rightClickListener +import net.horizonsend.ion.server.features.custom.items.component.StoredMultiblock import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.PrePackaged.getTokenData -import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName -import net.horizonsend.ion.server.miscellaneous.utils.text.itemName -import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName -import net.horizonsend.ion.server.miscellaneous.utils.updateLore import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor.GRAY import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack -import java.util.Locale object MultiblockToken : CustomItem( "MULTIBLOCK_TOKEN", @@ -29,20 +23,14 @@ object MultiblockToken : CustomItem( ItemFactory.unStackableCustomItem ) { override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { + addComponent(CustomComponentTypes.MULTIBLOCK_TYPE, StoredMultiblock) addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@MultiblockToken) { event, _, itemStack -> handleSecondaryInteract(event.player, itemStack, event) }) } fun constructFor(multiblock: Multiblock): ItemStack { - val base = constructItemStack() - .updateDisplayName(ofChildren(multiblock.getDisplayName(), text(" Token"))) - .updateLore(listOf( - text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", GRAY).itemName, - text("Variant: ${multiblock.javaClass.simpleName}", GRAY).itemName - )) - - return base.updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } + return constructItemStack().updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } } private fun handleSecondaryInteract(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index dfef164c64..887d67b9dd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.server.features.custom.items.component.CustomComponen import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.leftClickListener import net.horizonsend.ion.server.features.custom.items.component.Listener.Companion.rightClickListener +import net.horizonsend.ion.server.features.custom.items.component.StoredMultiblock import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged @@ -17,44 +18,38 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.text.itemName -import net.horizonsend.ion.server.miscellaneous.utils.updateMeta -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.format.NamedTextColor +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer +import net.kyori.adventure.text.Component.text import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack -import java.util.Locale object PackagedMultiblock : CustomItem( "PACKAGED_MULTIBLOCK", - ofChildren(Component.text("Packaged Null")), + ofChildren(text("Packaged Null")), ItemFactory.unStackableCustomItem ) { override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { + addComponent(CustomComponentTypes.MULTIBLOCK_TYPE, StoredMultiblock) + addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@PackagedMultiblock) { event, _, itemStack -> - handleSecondaryInteract(event.player, itemStack, event) + tryPlace(event.player, itemStack, event) }) addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@PackagedMultiblock) { event, _, itemStack -> - handlePrimaryInteract(event.player, itemStack, event) + tryPreview(event.player, itemStack, event) }) } fun createFor(multiblock: Multiblock): ItemStack { - return constructItemStack().updateMeta { - PrePackaged.setTokenData(multiblock, it.persistentDataContainer) - it.displayName(ofChildren(Component.text("Packaged "), multiblock.getDisplayName()).itemName) - it.lore(listOf( - Component.text("Multiblock: ${multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) }}", NamedTextColor.GRAY).itemName, - Component.text("Variant: ${multiblock.javaClass.simpleName}", NamedTextColor.GRAY).itemName, - Component.text("Left click to preview", NamedTextColor.GRAY).itemName, - Component.text("Right click to place", NamedTextColor.GRAY).itemName - )) - } + return constructItemStack() + .updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } + .updateDisplayName(ofChildren(text("Packaged "), multiblock.getDisplayName())) + .apply(::refreshLore) } - private fun handleSecondaryInteract(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { + private fun tryPlace(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { if (itemStack.type.isAir) return val packagedData = PrePackaged.getTokenData(itemStack) ?: run { @@ -62,7 +57,7 @@ object PackagedMultiblock : CustomItem( return } - val contents = itemStack.getData(DataComponentTypes.CONTAINER) ?: return livingEntity.userError("The packaged multiblock has no data!") + val contents = itemStack.getData(DataComponentTypes.CONTAINER)?.contents()?.toMutableList() ?: return livingEntity.userError("The packaged multiblock has no data!") val direction = livingEntity.facing val origin = PrePackaged.getOriginFromPlacement( @@ -81,14 +76,14 @@ object PackagedMultiblock : CustomItem( val entityData = itemStack.itemMeta.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) - runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, contents.contents(), entityData) }.onFailure { + runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, contents, entityData) }.onFailure { livingEntity.information("ERROR: $it") it.printStackTrace() }.onSuccess { // Drop remaining items in packaged multi val dropLocation = origin.getRelative(direction.oppositeFace).location.toCenterLocation() - for (item in contents.contents().filterNotNull()) { + for (item in contents.filterNotNull()) { livingEntity.world.dropItem(dropLocation, item) } } @@ -96,7 +91,7 @@ object PackagedMultiblock : CustomItem( itemStack.amount-- } - fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + fun tryPreview(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { if (livingEntity !is Player) return val packagedData = PrePackaged.getTokenData(itemStack) ?: run { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt index d3e40761fd..64e3be3189 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/PrePackaged.kt @@ -103,14 +103,11 @@ object PrePackaged { var usedItem: ItemStack? = null - if (itemSource != null) { - itemSource - .firstOrNull { requirement.itemRequirement.itemCheck(it) } - ?.let { - usedItem = it.clone() - requirement.itemRequirement.consume(it) - } - } + itemSource?.firstOrNull { requirement.itemRequirement.itemCheck(it) } + ?.let { + usedItem = it.clone() + requirement.itemRequirement.consume(it) + } val event = BlockPlaceEvent( existingBlock, @@ -247,7 +244,7 @@ object PrePackaged { @Suppress("UnstableApiUsage") val newState = Material.CHEST.createBlockData().createBlockState() as Chest packageFrom(availableItems, multiblock, newState.inventory) - return base.updateData(DataComponentTypes.CONTAINER, ItemContainerContents.containerContents(newState.inventory.contents.toList())) + return base.updateData(DataComponentTypes.CONTAINER, ItemContainerContents.containerContents(newState.inventory.contents.filterNotNull())) } /** From 9001f897a718f36ded10166b326ae3cd16e339da Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 20:14:47 -0600 Subject: [PATCH 384/500] Add side panel --- .../ion/common/utils/text/ComponentUtils.kt | 1 + .../custom/blocks/MultiblockWorkbench.kt | 33 ++++++++++++------- .../custom/misc/anvilinput/TextInputMenu.kt | 4 +-- .../multiblock/type/DisplayNameMultilblock.kt | 1 + .../multiblock/type/drills/DrillMultiblock.kt | 2 +- .../type/power/storage/PowerBankMultiblock.kt | 2 +- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt index 85287c8e37..9c1b262652 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt @@ -150,6 +150,7 @@ const val SPACE_RED_NEBULA_CHARACTER = '\uF8F8' const val SPACE_STARRY_BACKGROUND_CHARACTER = '\uF8F7' const val SPACE_MAIN_HYPERSPACE_ROUTES_CHARACTER = '\uF8F6' const val SPACE_MINOR_HYPERSPACE_ROUTES_CHARACTER = '\uF8F5' +const val MULTIBLOCK_WORKBENCH = '\uF8F4' // Custom characters end diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index de30dcc606..d0e521ffe1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -1,7 +1,10 @@ package net.horizonsend.ion.server.features.custom.blocks import io.papermc.paper.datacomponent.DataComponentTypes +import net.horizonsend.ion.common.utils.text.DEFAULT_GUI_WIDTH +import net.horizonsend.ion.common.utils.text.MULTIBLOCK_WORKBENCH import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry @@ -14,10 +17,12 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.PrePackaged.checkRequirements import net.horizonsend.ion.server.features.multiblock.PrePackaged.createPackagedItem +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDescription import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.horizonsend.ion.server.miscellaneous.utils.text.loreName import net.horizonsend.ion.server.miscellaneous.utils.updateData @@ -114,19 +119,25 @@ object MultiblockWorkbench : InteractableCustomBlock( } private fun setGuiOverlay(view: InventoryView) { - println(multiblocks.size) - - val text = GuiText("Multiblock Workbench") - .setSlotOverlay( - "# # # # # # # # #", - "# # # . . . . . .", - "# . # . . . . . .", - "# # # . . . . . ." - ) + val builder = GuiText("Multiblock Workbench") + .addBackground(GuiText.GuiBackground( + backgroundChar = MULTIBLOCK_WORKBENCH, + backgroundWidth = 250 - 9, + verticalShift = 10 + )) .add(currentMultiblock.getDisplayName(), line = 0) - .build() - view.setTitle(text) + val lines = currentMultiblock.getDescription().wrap(67) + for ((index, line) in lines.withIndex()) { + builder.add( + component = line.itemLore, // Use itemlore to give a white baseline + line = index + 1, // Don't overwrite the line 0 + verticalShift = -7, // Shift down to compensate +1 line + horizontalShift = DEFAULT_GUI_WIDTH + 2 // Shift over past the right +3 for padding + ) + } + + view.setTitle(builder.build()) } private fun refreshMultiblock(view: InventoryView) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/misc/anvilinput/TextInputMenu.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/misc/anvilinput/TextInputMenu.kt index 7843a9969b..71667840c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/misc/anvilinput/TextInputMenu.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/misc/anvilinput/TextInputMenu.kt @@ -65,12 +65,12 @@ class TextInputMenu( backgroundChar = ANVIL_BACKGROUND, horizontalShift = -52 )) + .add(title, line = -2, verticalShift = -3) + .add(description, line = -1, verticalShift = -2) .addBackground(GuiText.GuiBackground( backgroundChar = BACKGROUND_EXTENDER, verticalShift = -11 )) - .add(title, line = -2, verticalShift = -3) - .add(description, line = -1, verticalShift = -2) .build() val window = AnvilWindow.single() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt index 82edd664f9..fac530cd6f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt @@ -17,6 +17,7 @@ interface DisplayNameMultilblock { companion object { fun Multiblock.getDisplayName() = if (this is DisplayNameMultilblock) displayName else javaClass.simpleName.toComponent() + fun Multiblock.getDescription() = if (this is DisplayNameMultilblock) description else Component.text("Multiblock has no description.") fun Multiblock.getIcon(): ItemStack { val base = ItemStack(Material.CHEST) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index e28d0130c7..5103f4246f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -65,7 +65,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M line4 = null ) - override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), text(" Drill")) + override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), text(" Drill"), if (mirrored) text(" (Mirrored)") else empty()) override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { if (event.action != Action.RIGHT_CLICK_BLOCK) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt index a51fbdacf8..4f8e6c0d76 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/storage/PowerBankMultiblock.kt @@ -23,7 +23,7 @@ import org.bukkit.event.player.PlayerInteractEvent abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { abstract val maxPower: Int - override val description: Component = Component.text("Stores $maxPower power") + override val description: Component get() = Component.text("Stores $maxPower power") abstract val tierMaterial: Material override val name = "powerbank" From ef761324b1750c6b52fc2f56f4a9463c12159254 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sat, 11 Jan 2025 20:24:12 -0600 Subject: [PATCH 385/500] fix some multiblock names --- .../custom/blocks/MultiblockWorkbench.kt | 31 ++++++++++--------- .../multiblock/type/drills/DrillMultiblock.kt | 6 ++-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index d0e521ffe1..0431612d48 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -141,20 +141,23 @@ object MultiblockWorkbench : InteractableCustomBlock( } private fun refreshMultiblock(view: InventoryView) { - internalInventory.getItem(LEFT_BUTTON_SLOT)?.updateMeta { - it.lore(listOf( - if ((multiblockIndex - 1) >= 0) ofChildren( - text("Previous Multiblock: ", GRAY), multiblocks[multiblockIndex - 1].getDisplayName() - ).loreName else text("No previous multiblock", RED).loreName - )) - } - internalInventory.getItem(RIGHT_BUTTON_SLOT)?.updateMeta { - it.lore(listOf( - if ((multiblockIndex + 1) <= multiblocks.lastIndex) ofChildren( - text("Next Multiblock: ", GRAY), multiblocks[multiblockIndex + 1].getDisplayName() - ).loreName else text("No previous multiblock", RED).loreName - )) - } + internalInventory.getItem(LEFT_BUTTON_SLOT)?.updateLore(if ((multiblockIndex - 1) >= 0) + listOf( + ofChildren(text("Next Multiblock: ", GRAY), multiblocks[multiblockIndex - 1].getDisplayName()).loreName, + text(multiblocks[multiblockIndex - 1].javaClass.simpleName, GRAY).loreName + ) + else + listOf(text("No previous multiblock", RED).loreName) + ) + + internalInventory.getItem(RIGHT_BUTTON_SLOT)?.updateLore(if ((multiblockIndex + 1) <= multiblocks.lastIndex) + listOf( + ofChildren(text("Next Multiblock: ", GRAY), multiblocks[multiblockIndex + 1].getDisplayName()).loreName, + text(multiblocks[multiblockIndex + 1].javaClass.simpleName, GRAY).loreName + ) + else + listOf(text("No next multiblock", RED).loreName) + ) setGuiOverlay(view) refreshButtons() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index 5103f4246f..eac8f6bdab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -48,8 +48,8 @@ import java.util.EnumSet import java.util.UUID import kotlin.math.max -abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { - override val description: Component = text("Drills blocks in a ${javaClass.simpleName.substringBefore("Mirrored").substringAfter("DrillMultiblockTier").toInt() + 2} block radius") +abstract class DrillMultiblock(val tierText: String, val tierMaterial: Material) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { + override val description: Component = text("Drills blocks in a ${javaClass.simpleName.substringBefore("Mirrored").substringAfter("DrillMultiblockTier").toInt() + 2} block radius.") abstract val radius: Int abstract val coolDown: Int @@ -65,7 +65,7 @@ abstract class DrillMultiblock(tierText: String, val tierMaterial: Material) : M line4 = null ) - override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), text(" Drill"), if (mirrored) text(" (Mirrored)") else empty()) + override val displayName: Component get() = ofChildren(legacyAmpersand.deserialize(tierText), text(" Drill"), if (mirrored) text(" (Mirrored)") else empty()) override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { if (event.action != Action.RIGHT_CLICK_BLOCK) return From 6fee342225bb7fc69d9dad8a6a6b23f4f2ae5ff2 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 12 Jan 2025 01:49:23 -0600 Subject: [PATCH 386/500] Rewrite displays, todo make them work again --- .../ion/common/utils/text/Formatting.kt | 13 ++ .../server/command/misc/MultiblockCommand.kt | 28 ++- .../display/modular/DisplayHandlerHolder.kt | 4 + .../client/display/modular/DisplayHandlers.kt | 46 ++--- .../display/modular/TextDisplayHandler.kt | 98 +++++++--- .../client/display/modular/display/Display.kt | 174 ------------------ .../display/modular/display/DisplayModule.kt | 120 ++++++++++++ .../modular/display/DisplayPlayerManager.kt | 49 +++++ ...erDisplay.kt => FlowMeterDisplayModule.kt} | 13 +- ...Display.kt => PowerEntityDisplayModule.kt} | 7 +- ...tatusDisplay.kt => StatusDisplayModule.kt} | 6 +- ...isplay.kt => ComplexFluidDisplayModule.kt} | 6 +- ...{FluidDisplay.kt => FluidDisplayModule.kt} | 8 +- .../display/fluid/SimpleFluidDisplay.kt | 34 ---- .../display/fluid/SimpleFluidDisplayModule.kt | 20 ++ ...dDisplay.kt => SplitFluidDisplayModule.kt} | 9 +- .../multiblock/entity/MultiblockEntity.kt | 4 + .../entity/type/DisplayMultiblockEntity.kt | 3 +- .../entity/type/power/SimplePoweredEntity.kt | 6 +- .../multiblock/type/FurnaceMultiblock.kt | 9 - .../type/ammo/AmmoPressMultiblock.kt | 8 +- .../type/autocrafter/AutoCrafterMultiblock.kt | 8 +- .../farming/harvester/HarvesterMultiblock.kt | 8 +- .../type/farming/planter/PlanterMultiblock.kt | 8 +- .../type/fluid/ElectrolysisMultiblock.kt | 20 +- .../type/fluid/GasPowerPlantMultiblock.kt | 8 +- .../collector/PipedGasCollectorMultiblock.kt | 5 +- .../fluid/storage/FluidStorageMultiblock.kt | 4 +- .../type/misc/DecomposerMultiblock.kt | 8 +- .../type/power/charger/ChargerMultiblock.kt | 54 +++--- .../power/generator/GeneratorMultiblock.kt | 8 +- .../powerfurnace/PowerFurnaceMultiblock.kt | 8 +- .../type/printer/CarbonProcessorMultiblock.kt | 8 +- .../type/printer/PrinterMultiblock.kt | 8 +- .../nodes/cache/PowerTransportCache.kt | 2 +- .../transport/nodes/types/PowerNode.kt | 14 +- .../server/listener/misc/FurnaceListener.kt | 30 --- 37 files changed, 427 insertions(+), 439 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/{FlowMeterDisplay.kt => FlowMeterDisplayModule.kt} (77%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/{PowerEntityDisplay.kt => PowerEntityDisplayModule.kt} (83%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/{StatusDisplay.kt => StatusDisplayModule.kt} (75%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/{ComplexFluidDisplay.kt => ComplexFluidDisplayModule.kt} (70%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/{FluidDisplay.kt => FluidDisplayModule.kt} (81%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/{SplitFluidDisplay.kt => SplitFluidDisplayModule.kt} (66%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt index 8732869a39..b61a871634 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/Formatting.kt @@ -244,6 +244,19 @@ inline fun formatPaginatedMenu( return builder.build() } +inline fun formatPaginatedMenu( + entries: List, + command: String, + currentPage: Int, + maxPerPage: Int = 10, + color: TextColor = HEColorScheme.HE_MEDIUM_GRAY, + paramColor: TextColor = HE_LIGHT_GRAY, + footerSeparator: Component? = null, + entryProvider: (T, Int) -> Component +): Component { + return formatPaginatedMenu(entries.size, command, currentPage, maxPerPage, color, paramColor, footerSeparator) { index -> entryProvider.invoke(entries[index], index) } +} + /** * Builds a chat paginated menu * diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index f9ff6bd1c5..adf7793943 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -68,8 +68,8 @@ object MultiblockCommand : SLCommand() { return } - val message = Component.text() - .append(Component.text("Which type of $multiblockType are you trying to build? (Click one)")) + val message = text() + .append(text("Which type of $multiblockType are you trying to build? (Click one)")) .append(Component.newline()) for (tier in possibleTiers) { @@ -77,9 +77,9 @@ object MultiblockCommand : SLCommand() { val command = "/multiblock check $tierName ${sign.x} ${sign.y} ${sign.z}" - val tierText = bracketed(Component.text(tierName, NamedTextColor.DARK_GREEN, TextDecoration.BOLD)) + val tierText = bracketed(text(tierName, NamedTextColor.DARK_GREEN, TextDecoration.BOLD)) .clickEvent(ClickEvent.runCommand(command)) - .hoverEvent(Component.text(command).asHoverEvent()) + .hoverEvent(text(command).asHoverEvent()) message.append(tierText) if (possibleTiers.indexOf(tier) != possibleTiers.size - 1) message.append(Component.text(", ")) @@ -167,18 +167,16 @@ object MultiblockCommand : SLCommand() { val manager = sender.chunk.ion().multiblockManager val entities = manager.getAllMultiblockEntities().toList() - sender.sendMessage( - formatPaginatedMenu( - entities.size, - "/ionchunk dumpentities ${visual ?: false}", - page ?: 1, - ) { index -> - val (key, entity) = entities[index] - - val vec = toVec3i(key) + sender.sendMessage(formatPaginatedMenu( + entities, + "/ionchunk dumpentities ${visual == true}", + page ?: 1, + ) { entry, index -> + val (key, entity) = entry + val vec = toVec3i(key) - text("$vec : $entity") - }) + text("$vec : $entity") + }) if (visual == true) { for ((key, _) in entities) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt index bfca4d8b14..09ee4944a5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlerHolder.kt @@ -1,5 +1,9 @@ package net.horizonsend.ion.server.features.client.display.modular +import org.bukkit.World + interface DisplayHandlerHolder { val isAlive: Boolean + + fun handlerGetWorld(): World } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index acbccdaa41..b8baf22a94 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.client.display.modular import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.client.display.modular.display.Display +import net.horizonsend.ion.server.features.client.display.modular.display.DisplayModule import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -16,45 +16,27 @@ object DisplayHandlers : IonServerComponent() { } - fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg display: Display): TextDisplayHandler { + fun newMultiblockSignOverlay(entity: MultiblockEntity, vararg displayModule: (TextDisplayHandler) -> DisplayModule): TextDisplayHandler { val signDirection = entity.structureDirection.oppositeFace val signLocation = entity.getSignLocation() - return TextDisplayHandler( - entity, - entity.world, - signLocation.blockX, - signLocation.blockY, - signLocation.blockZ, - 0.0, - -0.1, - -0.39, // Back up towards the sign - signDirection, - *display - ) - } - - fun newBlockOverlay(holder: DisplayHandlerHolder, world: World, block: Vec3i, direction: BlockFace, vararg display: Display): TextDisplayHandler { - return TextDisplayHandler( - holder, - world, - block.x, - block.y, - block.z, - 0.0, - -0.15, - 0.55, - direction, - *display - ) - } + val builder = TextDisplayHandler.builder(entity, signLocation.blockX, signLocation.blockY, signLocation.blockZ) + .setOffset(offsetRight = 0.0, offsetUp = -0.1, offsetForward = -0.39) + .setDirection(signDirection) - fun newMultiText() { + displayModule.forEach(builder::addDisplay) + return builder.build() } - fun newSingleText() { + fun newBlockOverlay(holder: DisplayHandlerHolder, world: World, block: Vec3i, direction: BlockFace, vararg displayModule: (TextDisplayHandler) -> DisplayModule): TextDisplayHandler { + val builder = TextDisplayHandler.builder(holder, block.x, block.y, block.z) + .setOffset(offsetRight = 0.0, offsetUp = -0.1, offsetForward = -0.39) + .setDirection(direction) + + displayModule.forEach(builder::addDisplay) + return builder.build() } private val displayHandlers = ConcurrentHashMap.newKeySet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index dab3dc65e3..f846b54045 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -1,30 +1,27 @@ package net.horizonsend.ion.server.features.client.display.modular -import net.horizonsend.ion.server.features.client.display.modular.display.Display +import net.horizonsend.ion.server.features.client.display.modular.display.DisplayModule import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.rightFace import org.bukkit.Axis import org.bukkit.Location -import org.bukkit.World import org.bukkit.block.BlockFace -class TextDisplayHandler( +class TextDisplayHandler private constructor( val holder: DisplayHandlerHolder, - var world: World, - var blockX: Int, - var blockY: Int, - var blockZ: Int, + var anchorBlockX: Int, + var anchorBlockY: Int, + var anchorBlockZ: Int, val offsetRight: Double, val offsetUp: Double, val offsetForward: Double, var facing: BlockFace, - vararg display: Display ) { - val displays = listOf(*display) + var displayModules = listOf() fun update() { if (!holder.isAlive) { @@ -32,13 +29,13 @@ class TextDisplayHandler( return } - displays.forEach { - it.update() + displayModules.forEach { + it.runUpdates() } } fun remove() { - displays.forEach { + displayModules.forEach { it.remove() it.deRegister() } @@ -47,8 +44,8 @@ class TextDisplayHandler( } fun register(): TextDisplayHandler { - displays.forEach { - it.initialize(this) + displayModules.forEach { + it.runUpdates() it.register() } @@ -62,34 +59,79 @@ class TextDisplayHandler( val rightFace = if (forwardFace.axis == Axis.Y) BlockFace.NORTH else forwardFace.rightFace // Start from a center location, should be the same for every block - val centerLocation = Location(world, blockX + 0.5, blockY + 0.5, blockZ + 0.5) + val location = Location(holder.handlerGetWorld(), anchorBlockX + 0.5, anchorBlockY + 0.5, anchorBlockZ + 0.5) // Offset from the center location - centerLocation.add( + location.add( rightFace.modX * offsetRight + forwardFace.modX * offsetForward, offsetUp, rightFace.modZ * offsetRight + forwardFace.modZ * offsetForward ) - return centerLocation + return location } fun displace(movement: StarshipMovement) { - val oldFace = facing - facing = movement.displaceFace(oldFace) + facing = movement.displaceFace(facing) - val newX = movement.displaceX(blockX, blockZ) - val newY = movement.displaceY(blockY) - val newZ = movement.displaceZ(blockZ, blockX) + val newX = movement.displaceX(anchorBlockX, anchorBlockZ) + val newY = movement.displaceY(anchorBlockY) + val newZ = movement.displaceZ(anchorBlockZ, anchorBlockX) - blockX = newX - blockY = newY - blockZ = newZ + anchorBlockX = newX + anchorBlockY = newY + anchorBlockZ = newZ - for (display in displays) { - display.resetPosition(this) + for (display in displayModules) display.resetPosition() + } + + class Builder(val holder: DisplayHandlerHolder, val anchorBlockX: Int, val anchorBlockY: Int, val anchorBlockZ: Int) { + private val displays = mutableSetOf<(TextDisplayHandler) -> DisplayModule>() + + private var offsetForward = 0.0 + private var offsetRight = 0.0 + private var offsetUp = 0.0 + private var direction: BlockFace = BlockFace.NORTH + + fun addDisplay(build: (TextDisplayHandler) -> DisplayModule): Builder { + displays.add(build) + return this + } + + fun setOffset(offsetRight: Double, offsetUp: Double, offsetForward: Double): Builder { + this.offsetForward = offsetForward + this.offsetRight = offsetRight + this.offsetUp = offsetUp + return this } - update() + fun setDirection(face: BlockFace): Builder { + this.direction = face + return this + } + + fun build(): TextDisplayHandler { + val handler = TextDisplayHandler( + holder = holder, + anchorBlockX = anchorBlockX, + anchorBlockY = anchorBlockY, + anchorBlockZ = anchorBlockZ, + offsetRight = offsetRight, + offsetUp = offsetUp, + offsetForward = offsetForward, + facing = direction + ) + + handler.displayModules = displays.map { build -> build.invoke(handler) } + handler.register() + + return handler + } + } + + companion object { + fun builder(holder: DisplayHandlerHolder, anchorBlockX: Int, anchorBlockY: Int, anchorBlockZ: Int): Builder { + return Builder(holder, anchorBlockX, anchorBlockY, anchorBlockZ) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt deleted file mode 100644 index ddf521daa8..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/Display.kt +++ /dev/null @@ -1,174 +0,0 @@ -package net.horizonsend.ion.server.features.client.display.modular.display - -import io.papermc.paper.adventure.PaperAdventure -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.moveDisplayEntityPacket -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData -import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -import net.horizonsend.ion.server.miscellaneous.utils.axis -import net.horizonsend.ion.server.miscellaneous.utils.getChunkAtIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.kyori.adventure.text.Component -import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.Display.TextDisplay -import net.minecraft.world.entity.EntityType -import org.bukkit.Axis.Y -import org.bukkit.Bukkit.getPlayer -import org.bukkit.Color -import org.bukkit.Location -import org.bukkit.block.BlockFace -import org.bukkit.craftbukkit.CraftServer -import org.bukkit.craftbukkit.entity.CraftTextDisplay -import org.bukkit.util.Transformation -import org.joml.Quaternionf -import org.joml.Vector3f -import java.util.UUID - -abstract class Display( - private val offsetRight: Double, - private val offsetUp: Double, - private val offsetForward: Double, - val scale: Float -) { - private var shownPlayers = mutableSetOf() - - protected lateinit var handler: TextDisplayHandler - lateinit var entity: TextDisplay; private set - - open fun createEntity(parent: TextDisplayHandler): CraftTextDisplay = CraftTextDisplay( - IonServer.server as CraftServer, - TextDisplay(EntityType.TEXT_DISPLAY, parent.world.minecraft) - ).apply { - billboard = org.bukkit.entity.Display.Billboard.FIXED - viewRange = 5.0f - brightness = org.bukkit.entity.Display.Brightness(15, 15) - teleportDuration = 0 - backgroundColor = Color.fromARGB(0x00000000) - alignment = org.bukkit.entity.TextDisplay.TextAlignment.CENTER - - transformation = Transformation( - Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), - Vector3f(scale), - Quaternionf() - ) - } - - private var isInitializing = false - - val mutex = Any() - - fun getLocation(parent: TextDisplayHandler): Location { - val rightFace = if (parent.facing.axis == Y) BlockFace.NORTH else parent.facing.rightFace - - val offsetX = (rightFace.modX * offsetRight) + (parent.facing.modX * offsetForward) - val offsetY = offsetUp - val offsetZ = (rightFace.modZ * offsetRight) + (parent.facing.modZ * offsetForward) - - val parentLoc = parent.getLocation() - - return Location( - parent.world, - parentLoc.x + offsetX, - parentLoc.y + offsetY, - parentLoc.z + offsetZ - ) - } - - fun initialize(parent: TextDisplayHandler) = synchronized(mutex) { - if (isInitializing || this::handler.isInitialized) { - return@synchronized - } - - isInitializing = true - - this.handler = parent - - val location = getLocation(parent) - - runCatching { - entity = createEntity(parent).getNMSData( - location.x, - location.y, - location.z - ) - } - } - - fun resetPosition(parent: TextDisplayHandler) { - val location = getLocation(parent) - - entity.setTransformation(com.mojang.math.Transformation( - Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector2d(parent.facing.direction.toVector3f()), - Vector3f(scale), - Quaternionf() - )) - - shownPlayers.map(::getPlayer).forEach { player -> - if (player == null) return@forEach - moveDisplayEntityPacket(player.minecraft, entity, location.x, location.y, location.z) - } - } - - /** Registers this display handler */ - abstract fun register() - - /** Registers this display handler */ - abstract fun deRegister() - - abstract fun getText(): Component - - private fun setText(text: Component) { - entity.text = PaperAdventure.asVanilla(text) - } - - open fun remove() { - for (shownPlayer in shownPlayers) getPlayer(shownPlayer)?.minecraft?.connection?.send( - ClientboundRemoveEntitiesPacket(entity.id) - ) - - shownPlayers.clear() - } - - open fun display() { - if (!::handler.isInitialized) return - - update() - } - - private val distSquared = (50.0 * 50.0) - - open fun update() { - setText(getText()) - - val chunk = entity.level().world.getChunkAtIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return - val playerChunk = chunk.minecraft.`moonrise$getChunkAndHolder`().holder.playerProvider ?: return - //TODO fix this its bad - val viewers = playerChunk.getPlayers(chunk.minecraft.pos, false).toSet() - val newPlayers = viewers.filterNot { shownPlayers.contains(it.uuid) } - val old = viewers.filter { shownPlayers.contains(it.uuid) } - - for (player in newPlayers) { - broadcast(player) - } - - for (player in old) { - update(player) - } - - shownPlayers = viewers.mapTo(mutableSetOf()) { it.uuid } - } - - private fun update(player: ServerPlayer) { - entity.refreshEntityData(player) - } - - private fun broadcast(player: ServerPlayer) { - ClientDisplayEntities.sendEntityPacket(player, entity) - shownPlayers.add(player.uuid) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt new file mode 100644 index 0000000000..7fcd81572e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt @@ -0,0 +1,120 @@ +package net.horizonsend.ion.server.features.client.display.modular.display + +import io.papermc.paper.adventure.PaperAdventure +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntityFactory.getNMSData +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component +import net.minecraft.world.entity.Display.TextDisplay +import net.minecraft.world.entity.EntityType +import org.bukkit.Axis.Y +import org.bukkit.Color +import org.bukkit.Location +import org.bukkit.block.BlockFace +import org.bukkit.craftbukkit.CraftServer +import org.bukkit.craftbukkit.entity.CraftTextDisplay +import org.bukkit.util.Transformation +import org.joml.Quaternionf +import org.joml.Vector3f + +abstract class DisplayModule( + val handler: TextDisplayHandler, + + private val offsetRight: Double, + private val offsetUp: Double, + private val offsetForward: Double, + + val scale: Float +) { + val entity: TextDisplay = createEntity() + private val playerManager: DisplayPlayerManager = DisplayPlayerManager(entity) + + open fun createEntity(): TextDisplay { + val craftEntity = CraftTextDisplay( + IonServer.server as CraftServer, + TextDisplay(EntityType.TEXT_DISPLAY, handler.holder.handlerGetWorld().minecraft) + ) + + craftEntity.billboard = org.bukkit.entity.Display.Billboard.FIXED + craftEntity.viewRange = 5.0f + craftEntity.brightness = org.bukkit.entity.Display.Brightness(15, 15) + craftEntity.teleportDuration = 0 + craftEntity.backgroundColor = Color.fromARGB(0x00000000) + craftEntity.alignment = org.bukkit.entity.TextDisplay.TextAlignment.CENTER + + craftEntity.transformation = Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector(handler.facing.direction.toVector3f()), + Vector3f(scale), + Quaternionf() + ) + + val location = getLocation() + println("Location: $location") + + return craftEntity.getNMSData(location.x, location.y, location.z) + } + + fun getLocation(): Location { + val rightFace = if (handler.facing.axis == Y) BlockFace.NORTH else handler.facing.rightFace + + val offsetX = (rightFace.modX * offsetRight) + (handler.facing.modX * offsetForward) + val offsetY = offsetUp + val offsetZ = (rightFace.modZ * offsetRight) + (handler.facing.modZ * offsetForward) + + val parentLoc = handler.getLocation() + + return Location( + handler.holder.handlerGetWorld(), + parentLoc.x + offsetX, + parentLoc.y + offsetY, + parentLoc.z + offsetZ + ) + } + + fun resetPosition() { + val location = getLocation() + + entity.teleportTo(location.x, location.y, location.z) + entity.setTransformation(com.mojang.math.Transformation( + Vector3f(0f), + ClientDisplayEntities.rotateToFaceVector2d(handler.facing.direction.toVector3f()), + Vector3f(scale), + Quaternionf() + )) + + playerManager.runUpdates() + playerManager.sendTeleport() + } + + /** Registers this display handler */ + abstract fun register() + + /** Registers this display handler */ + abstract fun deRegister() + + abstract fun getText(): Component + + private fun setText(text: Component) { + entity.text = PaperAdventure.asVanilla(text) + } + + open fun remove() { + playerManager.sendRemove() + } + + open fun display() { + runUpdates() + } + + open fun runUpdates() { + val newText = getText() + setText(newText) + + playerManager.runUpdates() + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt new file mode 100644 index 0000000000..d9086abb2c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt @@ -0,0 +1,49 @@ +package net.horizonsend.ion.server.features.client.display.modular.display + +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.getAddEntityPacket +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket +import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.PositionMoveRotation +import net.minecraft.world.entity.Relative +import org.bukkit.Bukkit.getPlayer +import java.util.UUID + +class DisplayPlayerManager(val entity: net.minecraft.world.entity.Display) { + private var shownPlayers = mutableSetOf() + + fun sendTeleport() { + sendPacket(shownPlayers, ClientboundTeleportEntityPacket.teleport(entity.id, PositionMoveRotation.of(entity), setOf(), entity.onGround)) + } + + fun sendRemove() { + sendPacket(shownPlayers, ClientboundRemoveEntitiesPacket(entity.id)) + shownPlayers = mutableSetOf() + } + + fun sendPacket(players: Collection, packet: Packet<*>) { + players.mapNotNull(::getPlayer).forEach { bukkitPlayer -> bukkitPlayer.minecraft.connection.send(packet) } + } + + fun runUpdates() { + val chunk = entity.level().getChunkIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return + val viewers = chunk.`moonrise$getChunkAndHolder`().holder.`moonrise$getPlayers`(false).mapTo(mutableSetOf(), ServerPlayer::getUUID) + + val new = viewers.minus(shownPlayers) + val retained = viewers.intersect(shownPlayers) + + if (new.isNotEmpty()) { + val addEntity = getAddEntityPacket(entity) + sendPacket(new, addEntity) + } + + val all = retained.union(new) + if (all.isNotEmpty()) { + all.mapNotNull(::getPlayer).forEach { bukkitPlayer -> entity.refreshEntityData(bukkitPlayer.minecraft) } + } + + shownPlayers = viewers + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt similarity index 77% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt index eea1a47864..eeefff49ad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt @@ -9,15 +9,15 @@ import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW -import org.bukkit.craftbukkit.entity.CraftTextDisplay -class FlowMeterDisplay( +class FlowMeterDisplayModule( + handler: TextDisplayHandler, private val meter: PowerNode.PowerFlowMeter, offsetRight: Double, offsetUp: Double, offsetForward: Double, scale: Float -): Display(offsetRight, offsetUp, offsetForward, scale) { +): DisplayModule(handler, offsetRight, offsetUp, offsetForward, scale) { override fun register() {} override fun deRegister() {} @@ -29,11 +29,4 @@ class FlowMeterDisplay( val firstLine = text("E: ", YELLOW) val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Sec", GREEN)) } - - override fun createEntity(parent: TextDisplayHandler): CraftTextDisplay { - Throwable().printStackTrace() - - println("Create entity $this") - return super.createEntity(parent) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt similarity index 83% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt index b6857501d8..fbff25a46c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.client.display.modular.display import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.machine.PowerMachines.prefixComponent import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity @@ -9,15 +10,17 @@ import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor -class PowerEntityDisplay( +class PowerEntityDisplayModule( + handler: TextDisplayHandler, private val multiblockEntity: PoweredMultiblockEntity, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float, val title: Component? = null -): Display(offsetLeft, offsetUp, offsetBack, scale) { +): DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (PowerStorage) -> Unit = { + println("Updating display for $it") display() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt similarity index 75% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt index 96b885119d..10bb7e631f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt @@ -1,15 +1,17 @@ package net.horizonsend.ion.server.features.client.display.modular.display +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.kyori.adventure.text.Component -class StatusDisplay( +class StatusDisplayModule( + handler: TextDisplayHandler, private val statusSupplier: StatusMultiblockEntity.StatusManager, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float, -) : Display(offsetLeft, offsetUp, offsetBack, scale) { +) : DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: Runnable = Runnable { display() } override fun register() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt index ee34adeacd..137edbb8db 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt @@ -1,18 +1,20 @@ package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline -class ComplexFluidDisplay( +class ComplexFluidDisplayModule( + handler: TextDisplayHandler, container: StorageContainer, val title: Component, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float -) : FluidDisplay(container, offsetLeft, offsetUp, offsetBack, scale) { +) : FluidDisplayModule(handler, container, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { return ofChildren(title, newline(), formatFluid()) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt similarity index 81% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt index 3537e4000b..dc79282f37 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt @@ -1,20 +1,22 @@ package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.display.modular.display.Display +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.display.DisplayModule import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor -abstract class FluidDisplay( +abstract class FluidDisplayModule( + handler: TextDisplayHandler, val container: StorageContainer, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float -) : Display(offsetLeft, offsetUp, offsetBack, scale) { +) : DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (InternalStorage) -> Unit = { display() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt deleted file mode 100644 index 540244b9a7..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplay.kt +++ /dev/null @@ -1,34 +0,0 @@ -package net.horizonsend.ion.server.features.client.display.modular.display.fluid - -import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.space -import net.kyori.adventure.text.Component.text -import net.kyori.adventure.text.format.NamedTextColor -import net.kyori.adventure.text.format.TextDecoration -import org.bukkit.craftbukkit.entity.CraftTextDisplay - -class SimpleFluidDisplay( - storage: StorageContainer, - offsetLeft: Double, - offsetUp: Double, - offsetBack: Double, - scale: Float -) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { - override fun getText(): Component { - return ofChildren(formatFluid(), space(), container.internalStorage.getFluidType()?.displayName ?: empty) - } - - companion object { - val empty = text("Empty", NamedTextColor.GRAY, TextDecoration.ITALIC) - } - - override fun createEntity(parent: TextDisplayHandler): CraftTextDisplay { - Throwable().printStackTrace() - - println("Create entity $this") - return super.createEntity(parent) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt new file mode 100644 index 0000000000..f1f6752da0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.client.display.modular.display.fluid + +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.space + +class SimpleFluidDisplayModule( + handler: TextDisplayHandler, + storage: StorageContainer, + offsetLeft: Double, + offsetUp: Double, + offsetBack: Double, + scale: Float +) : FluidDisplayModule(handler, storage, offsetLeft, offsetUp, offsetBack, scale) { + override fun getText(): Component { + return ofChildren(formatFluid(), space(), container.internalStorage.getFluidType().displayName) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt similarity index 66% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt index b053638759..09d37e4021 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplay.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt @@ -1,19 +1,20 @@ package net.horizonsend.ion.server.features.client.display.modular.display.fluid import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.server.features.client.display.modular.display.fluid.SimpleFluidDisplay.Companion.empty +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.newline -class SplitFluidDisplay( +class SplitFluidDisplayModule( + handler: TextDisplayHandler, storage: StorageContainer, offsetLeft: Double, offsetUp: Double, offsetBack: Double, scale: Float -) : FluidDisplay(storage, offsetLeft, offsetUp, offsetBack, scale) { +) : FluidDisplayModule(handler, storage, offsetLeft, offsetUp, offsetBack, scale) { override fun getText(): Component { - return ofChildren(container.internalStorage.getFluidType()?.displayName ?: empty, newline(), formatFluid()) + return ofChildren(container.internalStorage.getFluidType().displayName, newline(), formatFluid()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 9139712044..de40a8adb8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -355,4 +355,8 @@ abstract class MultiblockEntity( private fun removeLinkages() { for (blockKey in linkages.values) manager.getLinkageManager().deRegisterLinkage(blockKey) } + + override fun handlerGetWorld(): World { + return world + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt index e4510f538a..a2c829083a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/DisplayMultiblockEntity.kt @@ -1,7 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.entity.type +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -interface DisplayMultiblockEntity { +interface DisplayMultiblockEntity : DisplayHandlerHolder { val displayHandler: TextDisplayHandler } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index a616443418..a9a784f305 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.power import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -39,8 +39,8 @@ abstract class SimplePoweredEntity( protected fun standardPowerDisplay(entity: SimplePoweredEntity): TextDisplayHandler = DisplayHandlers.newMultiblockSignOverlay( entity, - PowerEntityDisplay(entity, +0.0, +0.0, +0.0, 0.5f) - ).register() + { PowerEntityDisplayModule(it, entity, +0.0, +0.0, +0.0, 0.45f) } + ) override val inputsData: InputsData = InputsData.Builder(this) .addPowerInput(0, -1, 0) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt deleted file mode 100644 index 963e097511..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/FurnaceMultiblock.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.type - -import org.bukkit.block.Furnace -import org.bukkit.block.Sign -import org.bukkit.event.inventory.FurnaceBurnEvent - -interface FurnaceMultiblock { - fun onFurnaceTick(event: FurnaceBurnEvent, furnace: Furnace, sign: Sign) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index 93f46c4ddc..b5e09be316 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay -import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.attribute.AmmunitionRefillType import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes @@ -155,8 +155,8 @@ abstract class AmmoPressMultiblock : Multiblock(), EntityMultiblock + entity.displayHandler.displayModules.forEach { display -> player.information("Display $display") - player.information("Offset ${display.getLocation(handler)}") + player.information("Location ${display.getLocation()}") player.highlightBlock(display.entity.blockPosition().toVec3i(), 10L) } @@ -228,10 +228,10 @@ object ElectrolysisMultiblock : Multiblock(), EntityMultiblock, FurnaceMultiblock, DisplayNameMultilblock { - override val description: Component = Component.text("Charges powered items.") +abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { + override val description: Component = text("Charges powered items.") protected abstract val tierMaterial: Material protected abstract val powerPerSecond: Int - override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), Component.text(" Item Charger")) + override val displayName: Component = ofChildren(legacyAmpersand.deserialize(tierText), text(" Item Charger")) abstract val maxPower: Int @@ -77,16 +80,6 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMul line4 = tierText ) - override fun onFurnaceTick( - event: FurnaceBurnEvent, - furnace: Furnace, - sign: Sign - ) { - val entity = getMultiblockEntity(sign) ?: return - - entity.handleCharging(event, furnace) - } - override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): ChargerEntity { return ChargerEntity( data, @@ -109,33 +102,40 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMul z: Int, world: World, signDirection: BlockFace, - ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, signDirection, multiblock.maxPower), PoweredMultiblockEntity, LegacyMultiblockEntity { + ) : SimplePoweredEntity(data, multiblock, manager, x, y, z, world, signDirection, multiblock.maxPower), PoweredMultiblockEntity, LegacyMultiblockEntity, StatusTickedMultiblockEntity, SyncTickingMultiblockEntity { + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() override val displayHandler = standardPowerDisplay(this) - fun handleCharging(event: FurnaceBurnEvent, furnace: Furnace) { + override fun tick() { + val furnaceInventory = getInventory(0, 0, 0) as? FurnaceInventory ?: return + val availablePower = powerStorage.getPower() if (availablePower == 0) return - val item = event.fuel + val item = furnaceInventory.fuel ?: return val custom = item.customItem ?: return - if (custom.hasComponent(CustomComponentTypes.POWER_STORAGE)) - handleModern(item, custom, custom.getComponent(CustomComponentTypes.POWER_STORAGE), event, furnace, furnace.inventory, powerStorage.getPower()) + if (custom.hasComponent(CustomComponentTypes.POWER_STORAGE)) handleModern( + item, + custom, + custom.getComponent(CustomComponentTypes.POWER_STORAGE), + furnaceInventory, + powerStorage.getPower() + ) } fun handleModern( item: ItemStack, customItem: CustomItem, powerManager: PowerStorage, - event: FurnaceBurnEvent, - furnace: Furnace, inventory: FurnaceInventory, power: Int ) { if (powerManager.getMaxPower(customItem, item) == powerManager.getPower(item)) { val result = inventory.result if (result != null && result.type != Material.AIR) return - inventory.result = event.fuel + inventory.result = inventory.fuel inventory.fuel = null return } @@ -149,11 +149,7 @@ abstract class ChargerMultiblock(val tierText: String) : Multiblock(), EntityMul powerStorage.setPower(power - multiplier * item.amount) - furnace.cookTime = 20.toShort() - - event.isCancelled = false - event.isBurning = false - event.burnTime = 20 + sleepWithStatus(text("Working...", NamedTextColor.GREEN), 20) } override fun loadFromSign(sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt index 98c51fada0..a616b03d80 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/generator/GeneratorMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.power.generator import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay -import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule import net.horizonsend.ion.server.features.machine.GeneratorFuel import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -73,8 +73,8 @@ abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: M override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), - StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + { PowerEntityDisplayModule(it, this, +0.0, +0.0, +0.0, 0.45f) }, + { StatusDisplayModule(it, statusManager, +0.0, -0.10, +0.0, 0.45f) } ).register() override fun tick() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index 7e18c2033a..ec82607d14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -4,8 +4,8 @@ import com.google.common.cache.CacheBuilder import com.google.common.cache.CacheLoader import com.google.common.cache.LoadingCache import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay -import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity @@ -101,8 +101,8 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( this, - PowerEntityDisplay(this, +0.0, +0.0, +0.0, 0.45f), - StatusDisplay(statusManager, +0.0, -0.10, +0.0, 0.45f) + { PowerEntityDisplayModule(it, this, +0.0, +0.0, +0.0, 0.45f) }, + { StatusDisplayModule(it, statusManager, +0.0, -0.10, +0.0, 0.45f) } ).register() override fun tick() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt index fc4ee85891..192434c6a4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.printer import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplay -import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity @@ -100,8 +100,8 @@ object CarbonProcessorMultiblock : Multiblock(), EntityMultiblock) : TransportC .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) - .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(this, data.facing, loc) } + .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(this, data.facing, holder.getWorld(), loc) } .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index e991b24514..9c576a5821 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers -import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplay +import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplayModule import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache @@ -82,15 +82,19 @@ sealed interface PowerNode : Node { } } - data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, val location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { + data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, var world: World, var location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { override var isAlive: Boolean = true + override fun handlerGetWorld(): World { + return world + } + val displayHandler = DisplayHandlers.newBlockOverlay( this, cache.holder.getWorld(), toVec3i(location), face, - FlowMeterDisplay(this, 0.0, 0.0, 0.0, 0.7f) + { FlowMeterDisplayModule(it, this, 0.0, 0.0, 0.0, 0.7f) } ).register() private val STORED_AVERAGES = 20 @@ -133,7 +137,7 @@ sealed interface PowerNode : Node { avg = 0.0 } - return ofChildren(FlowMeterDisplay.firstLine, Component.text(avg, NamedTextColor.GREEN), FlowMeterDisplay.secondLine) + return ofChildren(FlowMeterDisplayModule.firstLine, Component.text(avg, NamedTextColor.GREEN), FlowMeterDisplayModule.secondLine) } override val pathfindingResistance: Double = 0.5 @@ -148,6 +152,8 @@ sealed interface PowerNode : Node { override fun displace(movement: StarshipMovement) { this.face = movement.displaceFace(this.face) + location = movement.displaceKey(location) + displayHandler.displace(movement) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt index 9c2cae1f9f..77d6271154 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/misc/FurnaceListener.kt @@ -3,47 +3,17 @@ package net.horizonsend.ion.server.listener.misc import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.attribute.SmeltingResultAttribute import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.MultiblockAccess -import net.horizonsend.ion.server.features.multiblock.type.FurnaceMultiblock import net.horizonsend.ion.server.listener.SLEventListener -import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.Material import org.bukkit.block.Furnace import org.bukkit.block.Sign import org.bukkit.block.data.Directional import org.bukkit.event.EventHandler -import org.bukkit.event.inventory.FurnaceBurnEvent import org.bukkit.event.inventory.FurnaceSmeltEvent import org.bukkit.inventory.ItemStack object FurnaceListener : SLEventListener() { - // thing for generally all furnace multiblocks - @EventHandler - fun onFurnaceBurn(event: FurnaceBurnEvent) { - val state = event.block.getState(false) as Furnace - - val directional = state.blockData as Directional - val signBlock = state.block.getRelativeIfLoaded(directional.facing) ?: return - - val type = signBlock.type - if (!type.isWallSign) return - - val sign = signBlock.getState(false) as Sign - val checkStructure = false - val loadChunks = false - val multiblock = MultiblockAccess.getMultiblock(sign, checkStructure, loadChunks) - - if (multiblock is FurnaceMultiblock) { - if (!multiblock.signMatchesStructure(sign, loadChunks = false, particles = false)) { - event.isCancelled = true - return - } - - multiblock.onFurnaceTick(event, state, sign) - } - } - // something with custom ores // NVM: Use FurnaceRecipe to remove the unstable "replace" implementation here // (FurnaceRecipe only uses Material for the source :skull:) From 2b612894eb888594de6c4028d40d970d0288e4cc Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 12 Jan 2025 15:12:43 -0600 Subject: [PATCH 387/500] Remove block entity data filter system --- .../custom/items/CustomItemRegistry.kt | 4 -- .../custom/items/misc/TransportFilterItem.kt | 45 --------------- .../transport/filters/FilterAccess.kt | 50 ----------------- .../transport/filters/FilterBlocks.kt | 55 ------------------- .../features/transport/filters/FilterData.kt | 36 ------------ .../features/transport/filters/FilterKey.kt | 30 ---------- .../features/transport/filters/FilterType.kt | 32 ----------- .../nodes/cache/FluidTransportCache.kt | 6 -- .../transport/nodes/cache/NodeCacheFactory.kt | 40 +------------- .../transport/nodes/types/FluidNode.kt | 17 ------ .../miscellaneous/registrations/Components.kt | 4 -- 11 files changed, 2 insertions(+), 317 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index 2aa9b37e4a..9464c5ef86 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -17,7 +17,6 @@ import net.horizonsend.ion.server.features.custom.items.component.Smeltable import net.horizonsend.ion.server.features.custom.items.misc.MultiblockToken import net.horizonsend.ion.server.features.custom.items.misc.MultimeterItem import net.horizonsend.ion.server.features.custom.items.misc.PackagedMultiblock -import net.horizonsend.ion.server.features.custom.items.misc.TransportFilterItem import net.horizonsend.ion.server.features.custom.items.misc.Wrench import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.custom.items.type.GasCanister @@ -45,7 +44,6 @@ import net.horizonsend.ion.server.features.custom.items.util.ItemFactory.Preset. import net.horizonsend.ion.server.features.custom.items.util.withComponent import net.horizonsend.ion.server.features.gas.Gasses import net.horizonsend.ion.server.features.machine.PowerMachines -import net.horizonsend.ion.server.features.transport.filters.FilterBlocks import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.map @@ -331,8 +329,6 @@ object CustomItemRegistry : IonServerComponent() { val WRENCH = register(Wrench) - val FLUID_FILTER: TransportFilterItem = register(TransportFilterItem("FLUID_FILTER", text("Fluid Filter")) { FilterBlocks.FLUID_FILTER }) - private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( text("$tierName ", tierColor), text("Power ", GOLD), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt deleted file mode 100644 index 637224efb0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/TransportFilterItem.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.horizonsend.ion.server.features.custom.items.misc - -import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.custom.items.util.ItemFactory -import net.horizonsend.ion.server.features.transport.filters.FilterBlock -import net.horizonsend.ion.server.features.transport.filters.FilterData -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FILTER_DATA -import net.horizonsend.ion.server.miscellaneous.utils.updateMeta -import net.kyori.adventure.text.Component -import org.bukkit.Material -import org.bukkit.block.Barrel -import org.bukkit.entity.LivingEntity -import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.BlockStateMeta -import org.bukkit.persistence.PersistentDataType.STRING -import java.util.function.Supplier - -class TransportFilterItem(identifier: String, displayName: Component, private val filterBlock: Supplier>) : CustomItem( - identifier, - displayName, - ItemFactory.stackableCustomItem -) { - fun constructItemStackB(): ItemStack { - return ItemStack(Material.BARREL).updateMeta { meta -> - meta as BlockStateMeta - meta.blockState = filterBlock.get().createState() - - meta.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) - meta.displayName(displayName) - } - } - - fun createFor(state: Barrel): ItemStack { - return constructItemStack().updateMeta { meta -> - meta.persistentDataContainer.set(FILTER_DATA, FilterData, state.persistentDataContainer.get(FILTER_DATA, FilterData) ?: return@updateMeta) - } - } - - fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { - if (event == null) return - event.isCancelled = false - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt deleted file mode 100644 index b11ba39433..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterAccess.kt +++ /dev/null @@ -1,50 +0,0 @@ -package net.horizonsend.ion.server.features.transport.filters - -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.misc.Wrench -import net.horizonsend.ion.server.features.transport.filters.FilterBlock.Companion.FILTER_STATE_TYPE -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.Material -import org.bukkit.block.Barrel -import org.bukkit.block.Block -import org.bukkit.event.EventHandler -import org.bukkit.event.EventPriority -import org.bukkit.event.player.PlayerInteractEvent - -object FilterAccess : IonServerComponent() { - @EventHandler(priority = EventPriority.NORMAL) - fun onPlayerInteract(event: PlayerInteractEvent) { - val clicked = event.clickedBlock ?: return - val state = clicked.state - - if (!FILTER_STATE_TYPE.isInstance(state)) return - state as Barrel - - val type = FilterBlocks.getFilterBlock(state) ?: return - - val interactedWith = event.item ?: return - if (interactedWith.customItem !is Wrench) { - event.isCancelled = true - return - } - - if (event.player.isSneaking) { - tryDrop(clicked, state, type) - return - } - - val filterData = state.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) - - type.openGUI(event.player, state, filterData) - } - - private fun tryDrop(block: Block, state: Barrel, type: FilterBlock<*>) { - val dropLocation = block.location.toCenterLocation() - val item = type.customItem.createFor(state) - - block.type = Material.AIR - - block.world.dropItemNaturally(dropLocation, item) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt deleted file mode 100644 index 00c432a412..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterBlocks.kt +++ /dev/null @@ -1,55 +0,0 @@ -package net.horizonsend.ion.server.features.transport.filters - -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.custom.items.misc.TransportFilterItem -import net.horizonsend.ion.server.features.transport.fluids.Fluid -import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.CUSTOM_ITEM -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FILTER_DATA -import org.bukkit.Material -import org.bukkit.block.Barrel -import org.bukkit.entity.Player -import org.bukkit.persistence.PersistentDataType.STRING -import java.util.function.Supplier - -object FilterBlocks : IonServerComponent() { - private val filters = mutableMapOf>() - fun all(): Map> = filters - - fun getFilterBlock(state: Barrel): FilterBlock<*>? { - val identifier = state.persistentDataContainer.get(CUSTOM_ITEM, STRING) ?: return null - return filters[identifier] - } - - val FLUID_FILTER: FilterBlock = registerFilter("FLUID_FILTER", CacheType.FLUID) { CustomItemRegistry.FLUID_FILTER } - - private fun registerFilter(identifier: String, cacheType: CacheType, customItemSupplier: Supplier): FilterBlock { - val data = FilterBlock(identifier, cacheType, customItemSupplier) - filters[identifier] = data - return data - } -} - -class FilterBlock(val identifier: String, val cacheType: CacheType, private val customItemSupplier: Supplier) { - val customItem get() = customItemSupplier.get() - - fun createState(): Barrel { - val baseState = FILTER_MATERIAL.createBlockData().createBlockState() as Barrel - baseState.persistentDataContainer.set(CUSTOM_ITEM, STRING, identifier) - return baseState - } - - fun openGUI(player: Player, state: Barrel, data: FilterData<*>?) { - if (data != null) { - state.persistentDataContainer.set(FILTER_DATA, FilterData, FilterData(false, mutableListOf())) - } - - println("$player $data") - } - - companion object { - val FILTER_MATERIAL = Material.BARREL - val FILTER_STATE_TYPE = Barrel::class - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt deleted file mode 100644 index 6e88f60ba9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ /dev/null @@ -1,36 +0,0 @@ -package net.horizonsend.ion.server.features.transport.filters - -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -class FilterData( - val isWhitelist: Boolean, - val entries: MutableList> -) { - companion object : PersistentDataType> { - override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - override fun getComplexType(): Class> = FilterData::class.java - - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*> { - val whitelist = primitive.getOrDefault(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, true) - val entries = primitive.getOrDefault(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()) - val formatted = entries.mapTo(mutableListOf()) { entry -> - FilterKey.fromPrimitive(entry, context) - } - - return FilterData(whitelist, formatted) - } - - override fun toPrimitive(complex: FilterData<*>, context: PersistentDataAdapterContext): PersistentDataContainer { - val data = context.newPersistentDataContainer() - - data.set(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, complex.isWhitelist) - val array = Array(complex.entries.size) { FilterKey.toPrimitive(complex.entries[it], context) } - data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, array) - - return data - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt deleted file mode 100644 index f8639b1217..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt +++ /dev/null @@ -1,30 +0,0 @@ -package net.horizonsend.ion.server.features.transport.filters - -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.persistence.PersistentDataAdapterContext -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -class FilterKey(val entry: T, val type: FilterType) { - companion object : PersistentDataType> { - override fun getComplexType(): Class> = FilterKey::class.java - override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterKey<*> { - val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! - val filterType = FilterType.filterTypes[filterTypeIdentifier]!! - - return FilterKey(filterType.retrieve(primitive)!!, filterType) - } - - override fun toPrimitive(complex: FilterKey<*>, context: PersistentDataAdapterContext): PersistentDataContainer { - val pdc = context.newPersistentDataContainer() - val typeIdentifier = complex.type.javaClass.simpleName - - pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) - complex.type.store(pdc, complex.entry) - - return pdc - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt deleted file mode 100644 index 5a72d8d5ae..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ /dev/null @@ -1,32 +0,0 @@ -package net.horizonsend.ion.server.features.transport.filters - -import com.manya.pdc.minecraft.ItemStackDataType -import net.horizonsend.ion.server.features.transport.fluids.Fluid -import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType -import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataContainer -import org.bukkit.persistence.PersistentDataType - -abstract class FilterType(val cacheType: CacheType, val typeClass: Class, val persistentDataType: PersistentDataType<*, T>) { - data object FluidType : FilterType(CacheType.FLUID, Fluid::class.java, FluidPersistentDataType) - data object ItemType : FilterType(CacheType.SOLAR_PANELS /*TODO*/, ItemStack::class.java, ItemStackDataType()) - - fun store(pdc: PersistentDataContainer, data: Any) { - if (!typeClass.isInstance(data)) return - @Suppress("UNCHECKED_CAST") - pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, data as T) - } - - fun retrieve(pdc: PersistentDataContainer): T? { - return pdc.get(NamespacedKeys.FILTER_ENTRY, persistentDataType) - } - - companion object { - val filterTypes = mutableMapOf>( - FluidType.javaClass.simpleName to FluidType, - ItemType.javaClass.simpleName to ItemType, - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 3e1b1c61f6..37c351f7f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -3,8 +3,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.filters.FilterBlocks -import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder @@ -43,10 +41,6 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) .addSimpleNode(Material.IRON_BLOCK, FluidNode.FluidMergeNode) .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) - .addFilterHandler(FilterBlocks.FLUID_FILTER) { data, location -> - @Suppress("UNCHECKED_CAST") - FluidNode.FluidFilterNode(data as FilterData, location) - } .build() override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index da013fe0ba..da92aecc55 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,30 +1,19 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import net.horizonsend.ion.server.features.transport.filters.FilterBlock -import net.horizonsend.ion.server.features.transport.filters.FilterBlocks -import net.horizonsend.ion.server.features.transport.filters.FilterData -import net.horizonsend.ion.server.features.transport.nodes.types.FilterNode import net.horizonsend.ion.server.features.transport.nodes.types.Node -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe import org.bukkit.Material -import org.bukkit.block.Barrel import org.bukkit.block.Block import org.bukkit.block.data.BlockData import kotlin.reflect.KClass -class NodeCacheFactory private constructor(private val materialHandlers: Map>, private val filterConstructor: FilterConstructor<*>?) { +class NodeCacheFactory private constructor(private val materialHandlers: Map>) { fun cache(block: Block): Node? { val type = block.getTypeSafe() ?: return null - if (filterConstructor != null) { - val result = tryCacheFilter(block) - if (result != null) return result - } - val materialFactory = materialHandlers[type] ?: return null val blockData = getBlockDataSafe(block.world, block.x, block.y, block.z) ?: return null @@ -32,21 +21,8 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map? { - filterConstructor!! - val barrel = block.state as? Barrel ?: return null - if (FilterBlocks.getFilterBlock(barrel) != filterConstructor.filterType) return null - - val pdc = barrel.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) - return filterConstructor.construct(pdc, toBlockKey(block.x, block.y, block.z)) - } - class Builder { val materialHandlers = mutableMapOf>() - private var filterHandler: FilterConstructor<*>? = null inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node): Builder { this.materialHandlers[material] = MaterialHandler(T::class, constructor) @@ -73,13 +49,8 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map addFilterHandler(filterType: FilterBlock, constructor: (FilterData<*>?, BlockKey) -> FilterNode): Builder { - this.filterHandler = FilterConstructor(filterType, constructor) - return this - } - fun build(): NodeCacheFactory { - return NodeCacheFactory(materialHandlers, filterHandler) + return NodeCacheFactory(materialHandlers) } } @@ -91,13 +62,6 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val filterType: FilterBlock, val constructor: (FilterData<*>?, BlockKey) -> FilterNode) { - @Synchronized - fun construct(blockData: FilterData<*>?, key: BlockKey): FilterNode { - return constructor.invoke(blockData, key) - } - } - companion object { fun builder(): Builder = Builder() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt index 90ad2b63d3..9b0237e096 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/FluidNode.kt @@ -2,8 +2,6 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.transport.filters.FilterData -import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -63,19 +61,4 @@ sealed interface FluidNode : Node { override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is LightningRodNode override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - - data class FluidFilterNode(val filterData: FilterData?, val location: BlockKey) : FluidNode, FilterNode { - override val pathfindingResistance: Double = 1.0 - - override fun canTransfer(resource: Fluid): Boolean { - if (filterData == null) return true - val containsEntry = filterData.entries.any { it.entry == resource } - - return filterData.isWhitelist == containsEntry - } - - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 2a775fb649..7cce13b108 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -91,8 +91,6 @@ import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeacons import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCooldown import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.filters.FilterAccess -import net.horizonsend.ion.server.features.transport.filters.FilterBlocks import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.old.Wires @@ -148,8 +146,6 @@ val components: List = listOf( PowerMachines, AreaShields, - FilterBlocks, - FilterAccess, TransportConfig.Companion, Pipes, Filters, From dab22a02f82653238e3e8be15e57ae3122df2708 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 12 Jan 2025 20:10:11 -0600 Subject: [PATCH 388/500] silly model creator, make use of them --- .../server/command/misc/MultiblockCommand.kt | 48 ++++ .../custom/blocks/MultiblockWorkbench.kt | 5 + .../custom/items/misc/MultiblockToken.kt | 7 +- .../custom/items/misc/PackagedMultiblock.kt | 3 + .../custom/items/type/CustomBlockItem.kt | 2 +- .../features/multiblock/ModelCreator.kt | 206 ++++++++++++++++++ .../multiblock/type/DisplayNameMultilblock.kt | 21 +- .../miscellaneous/registrations/Commands.kt | 2 + 8 files changed, 291 insertions(+), 3 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ModelCreator.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index adf7793943..dc72d6c359 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -18,26 +18,38 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.sendEntityPacket import net.horizonsend.ion.server.features.custom.items.misc.MultiblockToken +import net.horizonsend.ion.server.features.gui.GuiItems import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getIcon import net.horizonsend.ion.server.features.world.chunk.IonChunk.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextDecoration +import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.Sign import org.bukkit.command.CommandSender import org.bukkit.entity.Player import org.bukkit.event.block.BlockPlaceEvent +import org.bukkit.event.inventory.ClickType +import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.inventory.EquipmentSlot +import org.bukkit.inventory.ItemStack import org.bukkit.util.Vector +import xyz.xenondevs.invui.gui.PagedGui +import xyz.xenondevs.invui.gui.structure.Markers +import xyz.xenondevs.invui.item.ItemProvider +import xyz.xenondevs.invui.window.Window @CommandAlias("multiblock") object MultiblockCommand : SLCommand() { @@ -233,4 +245,40 @@ object MultiblockCommand : SLCommand() { ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) } } + + @Subcommand("menu") + fun onTestAll(sender: Player) { + val allItems = MultiblockRegistration.getAllMultiblocks().map { multiblock -> + object : GuiItems.AbstractButtonItem( + multiblock.getDisplayName().itemName, + multiblock.getIcon() + ) { + override fun handleClick(clickType: ClickType, player: Player, event: InventoryClickEvent) { + player.inventory.addItem(MultiblockToken.constructFor(multiblock)) + } + } + } + val gui = PagedGui.items() + .setStructure( + "x x x x x x x x x", + "x x x x x x x x x", + "x x x x x x x x x", + "x x x x x x x x x", + "< # # # # # # # >", + ) + .addIngredient('x', Markers.CONTENT_LIST_SLOT_HORIZONTAL) + .addIngredient('#', ItemProvider { ItemStack(Material.BLACK_STAINED_GLASS) }) + .addIngredient('<', GuiItems.PageLeftItem()) + .addIngredient('>', GuiItems.PageRightItem()) + .setContent(allItems) + .build() + + Window + .single() + .setGui(gui) + .setTitle("All Multiblocks") + .build(sender) + .open() + } + } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt index 0431612d48..8bc842547e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt @@ -19,6 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.PrePackaged.checkRequireme import net.horizonsend.ion.server.features.multiblock.PrePackaged.createPackagedItem import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDescription import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getIcon import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -113,6 +114,8 @@ object MultiblockWorkbench : InteractableCustomBlock( refreshButtons() } + noDropSlots.add(8) // Multiblock preview + // Perform full setup of the buttons refreshMultiblock(view) isSearching = false @@ -159,6 +162,8 @@ object MultiblockWorkbench : InteractableCustomBlock( listOf(text("No next multiblock", RED).loreName) ) + internalInventory.setItem(8, currentMultiblock.getIcon()) + setGuiOverlay(view) refreshButtons() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index a5a7a1f7a7..054a1246e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.custom.items.misc +import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem @@ -11,6 +12,8 @@ import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.PrePackaged.getTokenData +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getModel +import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text import org.bukkit.entity.Player @@ -30,7 +33,9 @@ object MultiblockToken : CustomItem( } fun constructFor(multiblock: Multiblock): ItemStack { - return constructItemStack().updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } + return constructItemStack() + .updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } + .updateData(DataComponentTypes.ITEM_MODEL, multiblock.getModel()) } private fun handleSecondaryInteract(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index 887d67b9dd..4d25598862 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -16,8 +16,10 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getModel import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text @@ -46,6 +48,7 @@ object PackagedMultiblock : CustomItem( return constructItemStack() .updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } .updateDisplayName(ofChildren(text("Packaged "), multiblock.getDisplayName())) + .updateData(DataComponentTypes.ITEM_MODEL, multiblock.getModel()) .apply(::refreshLore) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/CustomBlockItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/CustomBlockItem.kt index 1e16de4eb2..eba7e45c5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/CustomBlockItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/type/CustomBlockItem.kt @@ -10,7 +10,7 @@ import java.util.function.Supplier open class CustomBlockItem( identifier: String, - customModel: String, + val customModel: String, displayName: Component, private val customBlockSupplier: Supplier diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ModelCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ModelCreator.kt new file mode 100644 index 0000000000..d9ac55253c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/ModelCreator.kt @@ -0,0 +1,206 @@ +package net.horizonsend.ion.server.features.multiblock + +import co.aikar.commands.annotation.CommandAlias +import co.aikar.commands.annotation.CommandPermission +import co.aikar.commands.annotation.Default +import net.horizonsend.ion.common.extensions.success +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.command.SLCommand +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.averageBy +import net.minecraft.core.component.DataComponents +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import org.bukkit.craftbukkit.util.CraftMagicNumbers +import org.bukkit.entity.Player +import org.bukkit.util.Vector +import org.json.simple.JSONObject +import org.json.simple.parser.JSONParser +import java.io.BufferedReader +import java.io.BufferedWriter +import java.io.FileWriter +import java.io.InputStreamReader +import kotlin.system.measureTimeMillis + +@CommandPermission("ion.nope") +@CommandAlias("modelcreator") +object ModelCreator : SLCommand() { + val packDir = IonServer.dataFolder.resolve("generated/pack").apply { mkdirs() } + val itemModelPath = packDir.resolve("assets/horizonsend/models/item/multiblock").apply { mkdirs() } + val itemDefinitionPath = packDir.resolve("assets/horizonsend/items/multiblock").apply { mkdirs() } + + @Default + fun createModels(sender: Player) { + Tasks.async { + val time = measureTimeMillis { + val multiblocks = MultiblockRegistration.getAllMultiblocks() + + for (multiblock in multiblocks) { + makeModelFiles(multiblock) + } + } + + sender.success("success, $time ms") + } + } + + fun makeModelFiles(multiblock: Multiblock) { + val parent = if (multiblock is SignlessStarshipWeaponMultiblock<*>) "weapon" else multiblock.name.lowercase() + val name = multiblock.javaClass.simpleName.lowercase() + + val modelPath = itemModelPath.resolve(parent).apply { mkdirs() }.resolve("${name}.json") + + val modelWriter = BufferedWriter(FileWriter(modelPath)) + val model = createModel(multiblock.shape) + modelWriter.write(model) + modelWriter.close() + + val definitionPath = itemDefinitionPath.resolve(parent).apply { mkdirs() }.resolve("$name.json") + + val defintitionWriter = BufferedWriter(FileWriter(definitionPath)) + val definition = """ + { + "model": { + "type": "minecraft:model", + "model": "horizonsend:item/multiblock/$parent/$name" + } + } + """.trimIndent() + defintitionWriter.write(definition) + defintitionWriter.close() + } + + fun createModel(from: MultiblockShape): String { + val requirements = from.getRequirementMap(BlockFace.NORTH) + val examples: List = requirements.mapTo(mutableListOf()) { getMaterialTexture(it.value.example) }.distinct() + + val averageX = requirements.keys.averageBy { vec3i -> vec3i.x.toDouble() }.toInt() + val averageY = requirements.keys.averageBy { vec3i -> vec3i.y.toDouble() }.toInt() + val averageZ = requirements.keys.averageBy { vec3i -> vec3i.z.toDouble() }.toInt() + + val center = Vector(7.5 - averageX, 7.5 - averageY, 7.5 - averageZ) + + val builder = StringBuilder() + + builder.append("{\n") + builder.append("\t${getQuoted("credit")}: ${getQuoted(("GOOTAN"))},\n") + builder.append("\t${getQuoted("textures")}: {\n") + + examples + .withIndex() + .map { (index, example) -> + "\t\t${getQuoted("$index")}: ${getQuoted(example)},\n" + } + .forEach(builder::append) + + builder.append("\t\t${getQuoted("particle")}: ${getQuoted("block/iron_block")}\n") + + builder.append("\t},\n") + builder.append("\t${getQuoted("elements")}: [\n") + + val cubes = requirements.entries.joinToString(",\n") { (offset, requirement) -> + val requirementIndex = examples.indexOf(getMaterialTexture(requirement.example)) + val offsetVector = center.clone().add(offset.toVector()) + + createBlockString(offsetVector.x, offsetVector.y, offsetVector.z, requirementIndex) + } + + builder.append(cubes) + + builder.append("\n\t],\n") + builder.append("\t${getQuoted("display")}: {\n") // Display + builder.append("\t\t${getQuoted("fixed")}: {\n") // Fixed + + builder.append("\t\t\t${getQuoted("scale")}: [2.0, 2.0, 2.0]\n") + + builder.append("\t\t},\n") // Close fixed + + val maxExtent = maxOf( + requirements.keys.maxOf { it.x } - requirements.keys.minOf { it.x }, + requirements.keys.maxOf { it.y } - requirements.keys.minOf { it.y }, + requirements.keys.maxOf { it.z } - requirements.keys.minOf { it.z }, + ) + + val scale = (-(2.0 / 7.0) * maxExtent) + 4 + + builder.append("\t\t${getQuoted("gui")}: {\n") // gui + builder.append("\t\t\t${getQuoted("rotation")}: [45, -45, 0],\n") + builder.append("\t\t\t${getQuoted("scale")}: [$scale, $scale, $scale]\n") + + builder.append("\t\t}\n") // Close gui + builder.append("\t}\n") // Close display + + builder.append("}\n") // Close model + + return builder.toString() + } + + /** + * Creates a json block representing a single cube at the offset provided. + * The material index is computed ahead of time. + **/ + fun createBlockString(offsetX: Double, offsetY: Double, offsetZ: Double, materialIndex: Int): String { + val builder = StringBuilder() + + builder.append("\t\t{\n") // Cube block open { + builder.append("\t\t\t${getQuoted("from")}: [$offsetX, $offsetY, $offsetZ],\n") // Cube start corner + builder.append("\t\t\t${getQuoted("to")}: [${offsetX + 1}, ${offsetY + 1}, ${offsetZ + 1}],\n") // Cube close corner + builder.append("\t\t\t${getQuoted("rotation")}: {${getQuoted("angle")}: 0, ${getQuoted("axis")}: ${getQuoted("y")}, ${getQuoted("origin")}: [${offsetX + 0.5}, $offsetY, ${offsetY + 0.5}]},\n") // Empty rotation & origin + builder.append("\t\t\t${getQuoted("faces")}: {\n") // Faces { + + fun getUVString(face: BlockFace): String { + return "\t\t\t\t${getQuoted(face.name.lowercase())}: {${getQuoted("uv")}: [0, 0, 16, 16], ${getQuoted("texture")}: ${getQuoted("#$materialIndex")}}" + } + + val uvBlock = ADJACENT_BLOCK_FACES.joinToString(",\n", transform = ::getUVString) + builder.append(uvBlock) + + builder.append("\n\t\t\t}\n") // Close UV block + builder.append("\t\t}") // Close cube block + + return builder.toString() + } + + /** To ensure a lack of mistakes, handle the quotation of text in a separate function */ + private fun getQuoted(text: String): String = "\"$text\"" + + fun getMaterialTexture(blockData: BlockData): String { + val customBlock = CustomBlocks.getByBlockData(blockData) + if (customBlock != null) { + val item = customBlock.customItem + return "horizonsend:block/${item.customModel}" + } + + val material = blockData.material + + val nmsItem = CraftMagicNumbers.getBlock(material).asItem() + val nmsModel = nmsItem.components().get(DataComponents.ITEM_MODEL)!!.path + + val heAssetsFolder = IonServer.dataFolder.resolve("assets/blocks").apply { mkdirs() } + var withName = heAssetsFolder.resolve("$nmsModel.json") + + if (!withName.exists()) { + val closest = heAssetsFolder.listFiles().firstOrNull { file -> file.name.startsWith(nmsModel) } + + if (closest != null) { + withName = closest + } else { + return "blocks/iron_block" + } + } + + val reader = BufferedReader(InputStreamReader(withName.inputStream())) + val jsonObject = JSONParser().parse(reader) as JSONObject + val textures = jsonObject["textures"] as JSONObject + val keys = textures.keys + + if (keys.isEmpty()) fail { "why are there no textures" } + val textureString = textures[keys.first()] + + return textureString as String + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt index fac530cd6f..ed76d707e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/DisplayNameMultilblock.kt @@ -1,10 +1,15 @@ package net.horizonsend.ion.server.features.multiblock.type +import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updateLore +import net.kyori.adventure.key.Key import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.inventory.ItemStack @@ -21,13 +26,27 @@ interface DisplayNameMultilblock { fun Multiblock.getIcon(): ItemStack { val base = ItemStack(Material.CHEST) + .updateData(DataComponentTypes.ITEM_MODEL, getModel()) .updateDisplayName(getDisplayName()) return if (this is DisplayNameMultilblock) base -// .updateData(DataComponentTypes.ITEM_MODEL, iconModel) .updateLore(description.wrap(150)) else base } + + fun Multiblock.getModel(): Key { + val parent = if (this is SignlessStarshipWeaponMultiblock<*>) "weapon" else name.lowercase() + val name = javaClass.simpleName.lowercase() + + return NamespacedKeys.packKey("multiblock/$parent/$name") + } + + fun Multiblock.getModelString(): String { + val parent = if (this is SignlessStarshipWeaponMultiblock<*>) "weapon" else name.lowercase() + val name = javaClass.simpleName.lowercase() + + return "horizonsend:multiblock/$parent/$name" + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt index 29436416f6..6076bcddae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Commands.kt @@ -81,6 +81,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationCommands import net.horizonsend.ion.server.features.client.commands.HudCommand import net.horizonsend.ion.server.features.gui.custom.settings.commands.ControlSettingsCommand import net.horizonsend.ion.server.features.gui.custom.settings.commands.SettingsCommand +import net.horizonsend.ion.server.features.multiblock.ModelCreator import net.horizonsend.ion.server.features.player.NewPlayerProtection import net.horizonsend.ion.server.features.progression.achievements.AchievementsCommand import net.horizonsend.ion.server.features.sidebar.command.BookmarkCommand @@ -197,6 +198,7 @@ val commands: List = listOf( IonSitCommand, SuicideCommand, StructureCreator, + ModelCreator, NavigationCommand, DisplayDebug ) From f4998612d56e594274f47b3424316fb5695e915e Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Sun, 12 Jan 2025 20:52:11 -0600 Subject: [PATCH 389/500] Add more descriptions / display names --- .../features/custom/items/component/StoredMultiblock.kt | 7 ++++++- .../server/features/custom/items/misc/MultiblockToken.kt | 5 +++++ .../multiblock/type/autocrafter/AutoCrafterMultiblock.kt | 8 ++++++-- .../type/farming/harvester/HarvesterMultiblock.kt | 6 +++++- .../multiblock/type/farming/planter/PlanterMultiblock.kt | 6 +++++- .../features/multiblock/type/misc/CryoPodMultiblock.kt | 7 ++++++- .../features/multiblock/type/misc/DisposalMultiblock.kt | 9 +++++++-- .../type/power/generator/GeneratorMultiblock.kt | 7 ++++++- .../type/power/powerfurnace/PowerFurnaceMultiblock.kt | 7 ++++++- 9 files changed, 52 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt index 24c33516aa..81feffd329 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/component/StoredMultiblock.kt @@ -1,9 +1,11 @@ package net.horizonsend.ion.server.features.custom.items.component import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.attribute.CustomItemAttribute import net.horizonsend.ion.server.features.multiblock.PrePackaged +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDescription import net.horizonsend.ion.server.miscellaneous.utils.text.itemLore import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text @@ -20,7 +22,10 @@ object StoredMultiblock : CustomItemComponent, LoreManager { override fun getLines(customItem: CustomItem, itemStack: ItemStack): List { val multiblock = PrePackaged.getTokenData(itemStack) ?: return listOf() - return listOf( + val description = multiblock.getDescription().wrap(150).map { it.itemLore } + + return description + listOf( + Component.empty(), ofChildren(text("Multiblock: ", GRAY), text(multiblock.name.replaceFirstChar { char -> char.uppercase(Locale.getDefault()) })).itemLore, ofChildren(text("Variant: ", GRAY), text(multiblock.javaClass.simpleName)).itemLore, text("Left click to preview").itemLore, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index 054a1246e2..ef90c9c114 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.custom.items.misc import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes @@ -12,8 +13,10 @@ import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.features.multiblock.PrePackaged.getTokenData +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getDisplayName import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock.Companion.getModel import net.horizonsend.ion.server.miscellaneous.utils.updateData +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text import org.bukkit.entity.Player @@ -34,8 +37,10 @@ object MultiblockToken : CustomItem( fun constructFor(multiblock: Multiblock): ItemStack { return constructItemStack() + .updateDisplayName(ofChildren(text("Packaged "), multiblock.getDisplayName())) .updatePersistentDataContainer { PrePackaged.setTokenData(multiblock, this) } .updateData(DataComponentTypes.ITEM_MODEL, multiblock.getModel()) + .apply(::refreshLore) } private fun handleSecondaryInteract(livingEntity: Player, itemStack: ItemStack, event: PlayerInteractEvent) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 2d0d8b183e..bc8548ae78 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -18,6 +18,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.utils.front import net.horizonsend.ion.server.miscellaneous.utils.minecraft @@ -41,16 +42,19 @@ import java.util.Optional private const val POWER_USAGE_PER_INGREDIENT = 15 abstract class AutoCrafterMultiblock( - tierText: Component, + val tierText: Component, private val tierMaterial: Material, private val iterations: Int, -) : Multiblock(), EntityMultiblock { +) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "autocrafter" override val requiredPermission: String? = "ion.multiblock.autocrafter" open val mirrored: Boolean = false abstract val maxPower: Int + override val displayName: Component = ofChildren(tierText, text("Auto Crafter")) + override val description: Component get() = text("Executes the recipe outlined in the center dropper. Input items are consumed to craft the output.") + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index 7f2103cdab..c6400351c6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils @@ -32,7 +33,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.block.data.Ageable -abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock { +abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "harvester" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), @@ -41,6 +42,9 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I null ) + override val displayName: Component = text("Tier $tierNumber Harvester") + override val description: Component get() = text("Harvests crops. Crops will be harvested opposite of the sign, up to $regionDepth blocks away.") + val powerPerCrop: Int = 10 abstract val regionDepth: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 7c355d37cc..6805afed62 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -15,6 +15,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.kyori.adventure.text.Component @@ -32,7 +33,7 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.FurnaceInventory -abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock { +abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "planter" override val signText: Array = arrayOf( ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), @@ -41,6 +42,9 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int null ) + override val displayName: Component = text("Tier $tierNumber Planter") + override val description: Component get() = text("Plants crops on farmland. Crops will be planted opposite of the sign, up to $regionDepth blocks away.") + abstract val regionDepth: Int private val powerPerCrop: Int = 10 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt index ff75511dc3..0f67fbf34b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/CryoPodMultiblock.kt @@ -4,8 +4,10 @@ import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.features.machine.CryoPods import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.format.NamedTextColor @@ -15,7 +17,7 @@ import org.bukkit.block.sign.Side import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -object CryoPodMultiblock : Multiblock(), InteractableMultiblock { +object CryoPodMultiblock : Multiblock(), InteractableMultiblock, DisplayNameMultilblock { override val name = "cryopod" override val signText = createSignText( @@ -25,6 +27,9 @@ object CryoPodMultiblock : Multiblock(), InteractableMultiblock { line4 = null ) + override val displayName: Component = text("Cryopod") + override val description: Component get() = text("Provides a respawn point upon death, in place of beds. Works on ships.") + override fun MultiblockShape.buildStructure() { z(-2) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt index 56739fdeed..cbb821217a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/DisposalMultiblock.kt @@ -10,8 +10,10 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Material import org.bukkit.World @@ -19,11 +21,11 @@ import org.bukkit.block.BlockFace import org.bukkit.block.Sign import kotlin.math.roundToInt -abstract class AbstractDisposalMultiblock : Multiblock(), EntityMultiblock { +abstract class AbstractDisposalMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "incinerator" override var signText: Array = arrayOf( - Component.text("Incinerator").color(NamedTextColor.RED), + text("Incinerator").color(NamedTextColor.RED), null, null, null @@ -32,6 +34,9 @@ abstract class AbstractDisposalMultiblock : Multiblock(), EntityMultiblock { +abstract class GeneratorMultiblock(tierText: String, private val tierMaterial: Material) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "generator" abstract val speed: Double abstract val maxPower: Int + override val displayName: Component = text("Generator") + override val description: Component get() = text("Burns a fuel to generate to be used by other machines.") + override val signText = createSignText( line1 = "&2Power", line2 = "&8Generator", diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt index ec82607d14..3daf45cec0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/power/powerfurnace/PowerFurnaceMultiblock.kt @@ -18,8 +18,10 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.GREEN @@ -38,7 +40,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack import org.bukkit.inventory.ItemStack as BukkitItemStack import java.util.Optional -abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMultiblock { +abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "powerfurnace" abstract val maxPower: Int @@ -52,6 +54,9 @@ abstract class PowerFurnaceMultiblock(tierText: String) : Multiblock(), EntityMu line4 = tierText ) + override val displayName: Component = text("Power Furnace") + override val description: Component = text("Smelts items using power instead of fuel.") + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { From 10b8509db589c160dab00f0c3526be040b04f3b0 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 13 Jan 2025 11:06:59 -0600 Subject: [PATCH 390/500] remove printlns --- .../features/client/display/modular/display/DisplayModule.kt | 2 +- .../client/display/modular/display/PowerEntityDisplayModule.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt index 7fcd81572e..63ebf4e965 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt @@ -54,7 +54,7 @@ abstract class DisplayModule( ) val location = getLocation() - println("Location: $location") +// println("Location: $location") return craftEntity.getNMSData(location.x, location.y, location.z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt index fbff25a46c..dc7ba38c90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt @@ -20,7 +20,7 @@ class PowerEntityDisplayModule( val title: Component? = null ): DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (PowerStorage) -> Unit = { - println("Updating display for $it") +// println("Updating display for $it") display() } From 577bc330e00b0d358d1a0c4107125b7025e9e8d6 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Mon, 13 Jan 2025 11:57:23 -0600 Subject: [PATCH 391/500] Add a basic path cache --- .../custom/items/misc/MultimeterItem.kt | 4 +- .../nodes/cache/FluidTransportCache.kt | 14 +++-- .../nodes/cache/PowerTransportCache.kt | 12 ++--- .../transport/nodes/cache/TransportCache.kt | 52 +++++++++++++++++++ .../transport/util/NodePathfinding.kt | 11 ++-- 5 files changed, 73 insertions(+), 20 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index ed5e3f17b0..55f42d2fe9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -95,8 +95,8 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na val firstNode = cacheType.get(firstChunk).getOrCache(firstPoint) ?: return audience.information("There is no node at ${toVec3i(firstPoint)}") - val path = getIdealPath(audience, Node.NodePositionData(firstNode, world, firstPoint, BlockFace.SELF), secondPoint) - val resistance = calculatePathResistance(path) ?: return audience.userError("There is no path connecting these nodes") + val path = getIdealPath(audience, Node.NodePositionData(firstNode, world, firstPoint, BlockFace.SELF), secondPoint) ?: return audience.userError("There is no path connecting these nodes") + val resistance = calculatePathResistance(path) audience.information("The resistance from ${firstNode.javaClass.simpleName} at ${toVec3i(firstPoint)} to ${toVec3i(secondPoint)} at ${toVec3i(secondPoint)} is $resistance") } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 37c351f7f2..af6677dc93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -11,8 +11,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis @@ -98,17 +96,17 @@ class FluidTransportCache(holder: CacheHolder): TransportCa val numDestinations = filteredDestinations.size - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, filteredDestinations[it], holder.nodeProvider) { node, _ -> - (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) ?: true) + val paths: Array = Array(numDestinations) { + getOrCachePath(source, filteredDestinations[it]) { node, _ -> + (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) != false) } - }.getOrNull() } + } var maximumResistance: Double = -1.0 // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { - val res = calculatePathResistance(paths[it]) + val res = paths[it]?.resistance if (res != null && maximumResistance < res) maximumResistance = res res @@ -147,7 +145,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa val realTaken = toSend - remainder remainingAmount -= realTaken - completeChain(paths[index], realTaken) + completeChain(paths[index]?.traversedNodes, realTaken) if (remainder == 0) continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 837e331a92..9104180d00 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -10,8 +10,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -119,15 +117,15 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val numDestinations = filteredDestinations.size - val paths: Array?> = Array(numDestinations) { runCatching { - getIdealPath(source, filteredDestinations[it], holder.nodeProvider) - }.getOrNull() } + val paths: Array = Array(numDestinations) { + getOrCachePath(source, filteredDestinations[it]) + } var maximumResistance: Double = -1.0 // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { - val res = calculatePathResistance(paths[it]) + val res = paths[it]?.resistance if (res != null && maximumResistance < res) maximumResistance = res res @@ -170,7 +168,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC runCatching { // Update power flow meters - paths[index]?.forEach { if (it.type is PowerFlowMeter) it.type.onCompleteChain(realTaken) } + paths[index]?.traversedNodes?.forEach { if (it.type is PowerFlowMeter) it.type.onCompleteChain(realTaken) } } if (remainder == 0) continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 9198bc8c39..6835355f66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import com.google.common.collect.TreeBasedTable import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity @@ -9,6 +10,8 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ComplexNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -21,9 +24,12 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isAdjacent import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded +import net.horizonsend.ion.server.miscellaneous.utils.set import org.bukkit.block.Block import org.bukkit.block.BlockFace +import java.util.Optional import java.util.concurrent.ConcurrentHashMap +import kotlin.jvm.optionals.getOrNull abstract class TransportCache(val holder: CacheHolder<*>) { private var cache: ConcurrentHashMap = ConcurrentHashMap() @@ -178,11 +184,57 @@ abstract class TransportCache(val holder: CacheHolder<*>) { if (current.type is T && check(current)) destinations.add(current.position) + visitQueue.addAll(current.getNextNodes(holder.nodeProvider, null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) } return destinations.toList() } + + /** + * + **/ + private val simplePathCache = TreeBasedTable.create>() + + fun getOrCachePath(origin: Node.NodePositionData, destination: BlockKey, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): PathfindingReport? { + if (simplePathCache.contains(origin.position, destination)) { + return simplePathCache.get(origin.position, destination)?.getOrNull() + } + + val path = runCatching { getIdealPath(origin, destination, holder.nodeProvider, pathfindingFilter) }.getOrNull() + + if (path == null) { + simplePathCache[origin.position, destination] = Optional.empty() + return null + } + + val resistance = calculatePathResistance(path) + + val report = PathfindingReport(path, resistance) + + simplePathCache[origin.position, destination] = Optional.of(report) + return report + } + + data class PathfindingReport(val traversedNodes: Array, val resistance: Double) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as PathfindingReport + + if (resistance != other.resistance) return false + if (!traversedNodes.contentEquals(other.traversedNodes)) return false + + return true + } + + override fun hashCode(): Int { + var result = resistance.hashCode() + result = 31 * result + traversedNodes.contentHashCode() + return result + } + } } // I hate this function but it works diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 8b8c435b2d..47f0502de7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -21,7 +21,12 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ -fun getIdealPath(from: Node.NodePositionData, to: BlockKey, cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): Array? { +fun getIdealPath( + from: Node.NodePositionData, + to: BlockKey, + cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, + pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null +): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. @@ -155,6 +160,6 @@ data class PathfindingNodeWrapper( // } -fun calculatePathResistance(path: Array?): Double? { - return path?.sumOf { it.type.pathfindingResistance } +fun calculatePathResistance(path: Array): Double { + return path.sumOf { it.type.pathfindingResistance } } From bdc3b35e7264e89966ceaef90bdae70d5d72c244 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Tue, 14 Jan 2025 00:06:21 -0600 Subject: [PATCH 392/500] Fix display entities, code cleanup and remove magic numbers --- .../ion/common/utils/text/ComponentUtils.kt | 4 --- .../client/display/ClientDisplayEntities.kt | 17 ++++++++-- .../client/display/modular/DisplayHandlers.kt | 5 ++- .../display/modular/TextDisplayHandler.kt | 2 +- .../modular/display/DisplayConstants.kt | 34 +++++++++++++++++++ .../display/modular/display/DisplayModule.kt | 21 +++++------- .../modular/display/DisplayPlayerManager.kt | 10 +++--- .../modular/display/FlowMeterDisplayModule.kt | 2 +- .../display/PowerEntityDisplayModule.kt | 19 +++++++---- .../modular/display/StatusDisplayModule.kt | 12 +++---- .../fluid/ComplexFluidDisplayModule.kt | 2 +- .../display/fluid/FluidDisplayModule.kt | 2 +- .../display/fluid/SimpleFluidDisplayModule.kt | 2 +- .../display/fluid/SplitFluidDisplayModule.kt | 2 +- .../custom/items/CustomItemRegistry.kt | 8 ++--- .../entity/type/power/SimplePoweredEntity.kt | 2 +- .../type/ammo/AmmoPressMultiblock.kt | 4 +-- .../type/autocrafter/AutoCrafterMultiblock.kt | 4 +-- .../farming/harvester/HarvesterMultiblock.kt | 4 +-- .../type/farming/planter/PlanterMultiblock.kt | 4 +-- .../type/fluid/ElectrolysisMultiblock.kt | 10 +++--- .../type/fluid/GasPowerPlantMultiblock.kt | 4 +-- .../fluid/storage/FluidStorageMultiblock.kt | 3 +- .../type/misc/DecomposerMultiblock.kt | 4 +-- .../power/generator/GeneratorMultiblock.kt | 4 +-- .../powerfurnace/PowerFurnaceMultiblock.kt | 4 +-- .../type/power/storage/PowerBankMultiblock.kt | 11 +----- .../type/printer/CarbonProcessorMultiblock.kt | 4 +-- .../type/printer/PrinterMultiblock.kt | 4 +-- .../transport/nodes/types/PowerNode.kt | 3 +- 30 files changed, 123 insertions(+), 88 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt index 9c1b262652..75dd43459c 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt @@ -18,7 +18,6 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.WHITE import net.kyori.adventure.text.format.Style -import net.kyori.adventure.text.format.Style.style import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextDecoration import net.kyori.adventure.text.minimessage.MiniMessage @@ -89,9 +88,6 @@ fun formatLink(showText: String, link: String): Component { .hoverEvent(text(link)) } -//Shortcut -fun text(string: String, decoration: TextDecoration): Component = text(string, style(decoration)) - // Allow static imports val OBFUSCATED = TextDecoration.OBFUSCATED val BOLD = TextDecoration.BOLD diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt index 150aa4a0f9..11cf5553fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/ClientDisplayEntities.kt @@ -10,7 +10,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.kyori.adventure.audience.Audience import net.kyori.adventure.audience.ForwardingAudience -import net.minecraft.core.BlockPos import net.minecraft.network.protocol.game.ClientboundAddEntityPacket import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket @@ -20,6 +19,7 @@ import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.PositionMoveRotation import net.minecraft.world.entity.Relative import net.minecraft.world.entity.monster.Slime +import net.minecraft.world.phys.Vec3 import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.block.data.BlockData @@ -387,8 +387,19 @@ object ClientDisplayEntities : IonServerComponent() { */ fun viewDistanceFactor(viewDistance: Int) = (0.003125 * viewDistance).toFloat() - fun getAddEntityPacket(entity: net.minecraft.world.entity.Entity): ClientboundAddEntityPacket { - return ClientboundAddEntityPacket(entity, 0, BlockPos(entity.blockX, entity.blockY, entity.blockZ)) + return ClientboundAddEntityPacket( + entity.id, + entity.getUUID(), + entity.trackingPosition().x(), + entity.trackingPosition().y(), + entity.trackingPosition().z(), + entity.rotationVector.x, + entity.rotationVector.y, + entity.type, + 0, + Vec3(Vector3f()), + entity.yHeadRot.toDouble() + ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index b8baf22a94..8fccfc833b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.server.features.client.display.modular.display.Displa import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import java.util.concurrent.ConcurrentHashMap @@ -21,7 +20,7 @@ object DisplayHandlers : IonServerComponent() { val signLocation = entity.getSignLocation() val builder = TextDisplayHandler.builder(entity, signLocation.blockX, signLocation.blockY, signLocation.blockZ) - .setOffset(offsetRight = 0.0, offsetUp = -0.1, offsetForward = -0.39) + .setOffset(offsetRight = 0.0, offsetUp = -0.5, offsetForward = -0.39) .setDirection(signDirection) displayModule.forEach(builder::addDisplay) @@ -29,7 +28,7 @@ object DisplayHandlers : IonServerComponent() { return builder.build() } - fun newBlockOverlay(holder: DisplayHandlerHolder, world: World, block: Vec3i, direction: BlockFace, vararg displayModule: (TextDisplayHandler) -> DisplayModule): TextDisplayHandler { + fun newBlockOverlay(holder: DisplayHandlerHolder, block: Vec3i, direction: BlockFace, vararg displayModule: (TextDisplayHandler) -> DisplayModule): TextDisplayHandler { val builder = TextDisplayHandler.builder(holder, block.x, block.y, block.z) .setOffset(offsetRight = 0.0, offsetUp = -0.1, offsetForward = -0.39) .setDirection(direction) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt index f846b54045..c39a0c79b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/TextDisplayHandler.kt @@ -45,8 +45,8 @@ class TextDisplayHandler private constructor( fun register(): TextDisplayHandler { displayModules.forEach { - it.runUpdates() it.register() + it.runUpdates() } DisplayHandlers.registerHandler(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt new file mode 100644 index 0000000000..685265aad1 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.client.display.modular.display + +// Text display scale that matches the line height of sign text +const val MATCH_SIGN_FONT_SIZE = 0.416f + +// In blocks, the height of a single line of text on a sign +const val SIGN_LINE_HEIGHT = 0.0728 +// In blocks, the amount of space between lines of text on a sign +const val SIGN_LINE_SPACING = 0.03134479271 + +// In blocks, the amount of padding between the bottom of the block and the bottom of the sign model +const val SIGN_BOTTOM_PADDING = 0.26895854398 +// In blocks, the amount of padding between the top of the block and the top of the sign model +const val SIGN_TOP_PADDING = 0.22851365015 +// In blocks, height of the sign model +const val SIGN_HEIGHT = 0.50252780586 + +// In blocks, amount of empty space between the top of the sign model and the top of the text of the first line +const val SIGN_TEXT_PADDING_TOP = 0.04246713852 +// In blocks, amount of empty space between the bottom of the sign model and the bottom of the text of the last line +const val SIGN_TEXT_PADDING_BOTTOM = 0.07280080889 + +// Gets a Y offset that corresponds to the line number provided +fun getLinePos(lineNum: Int): Double { + val alignmentOffset = SIGN_LINE_HEIGHT / 7.0 + val originLineOffset = SIGN_TOP_PADDING + SIGN_TEXT_PADDING_TOP + val lineOffset = (SIGN_LINE_SPACING + SIGN_LINE_HEIGHT) * lineNum + + return ((1.0 - originLineOffset) - lineOffset) + alignmentOffset +} + +val POWER_TEXT_LINE = getLinePos(3) +val STATUS_TEXT_LINE = getLinePos(4) + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt index 63ebf4e965..81616e63d5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt @@ -48,7 +48,7 @@ abstract class DisplayModule( craftEntity.transformation = Transformation( Vector3f(0f), - ClientDisplayEntities.rotateToFaceVector(handler.facing.direction.toVector3f()), + ClientDisplayEntities.rotateToFaceVector2d(handler.facing.direction.toVector3f()), Vector3f(scale), Quaternionf() ) @@ -97,24 +97,19 @@ abstract class DisplayModule( /** Registers this display handler */ abstract fun deRegister() - abstract fun getText(): Component + abstract fun buildText(): Component - private fun setText(text: Component) { + private fun updateText(text: Component) { entity.text = PaperAdventure.asVanilla(text) } - open fun remove() { - playerManager.sendRemove() - } - - open fun display() { - runUpdates() - } - open fun runUpdates() { - val newText = getText() - setText(newText) + updateText(buildText()) playerManager.runUpdates() } + + open fun remove() { + playerManager.sendRemove() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt index d9086abb2c..94145c4eba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayPlayerManager.kt @@ -27,6 +27,11 @@ class DisplayPlayerManager(val entity: net.minecraft.world.entity.Display) { players.mapNotNull(::getPlayer).forEach { bukkitPlayer -> bukkitPlayer.minecraft.connection.send(packet) } } + fun sendAddEntity(players: Set) { + val addEntity = getAddEntityPacket(entity) + sendPacket(players, addEntity) + } + fun runUpdates() { val chunk = entity.level().getChunkIfLoaded(entity.x.toInt().shr(4), entity.z.toInt().shr(4)) ?: return val viewers = chunk.`moonrise$getChunkAndHolder`().holder.`moonrise$getPlayers`(false).mapTo(mutableSetOf(), ServerPlayer::getUUID) @@ -34,10 +39,7 @@ class DisplayPlayerManager(val entity: net.minecraft.world.entity.Display) { val new = viewers.minus(shownPlayers) val retained = viewers.intersect(shownPlayers) - if (new.isNotEmpty()) { - val addEntity = getAddEntityPacket(entity) - sendPacket(new, addEntity) - } + if (new.isNotEmpty()) sendAddEntity(new) val all = retained.union(new) if (all.isNotEmpty()) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt index eeefff49ad..adb206030e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt @@ -21,7 +21,7 @@ class FlowMeterDisplayModule( override fun register() {} override fun deRegister() {} - override fun getText(): Component { + override fun buildText(): Component { return meter.formatFlow() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt index dc7ba38c90..f5eabdd6f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/PowerEntityDisplayModule.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.client.display.modular.display +import io.papermc.paper.adventure.PaperAdventure import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.machine.PowerMachines.prefixComponent import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage @@ -13,15 +15,14 @@ import net.kyori.adventure.text.format.NamedTextColor class PowerEntityDisplayModule( handler: TextDisplayHandler, private val multiblockEntity: PoweredMultiblockEntity, - offsetLeft: Double, - offsetUp: Double, - offsetBack: Double, - scale: Float, + offsetLeft: Double = 0.0, + offsetUp: Double = POWER_TEXT_LINE, + offsetBack: Double = 0.0, + scale: Float = MATCH_SIGN_FONT_SIZE, val title: Component? = null ): DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (PowerStorage) -> Unit = { -// println("Updating display for $it") - display() + runUpdates() } override fun register() { @@ -32,9 +33,13 @@ class PowerEntityDisplayModule( multiblockEntity.powerStorage.removeUpdateHandler(updateHandler) } - override fun getText(): Component { + override fun buildText(): Component { return title?.let { ofChildren(it, newline(), formatPower()) } ?: formatPower() } private fun formatPower(): Component = ofChildren(prefixComponent, text(multiblockEntity.powerStorage.getPower(), NamedTextColor.GREEN)) + + override fun toString(): String { + return "PowerEntityDisplayModule{TextPlain: ${PaperAdventure.asAdventure(entity.text).plainText()}}, Displaying at ${getLocation()}" + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt index 10bb7e631f..00b8c2042e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/StatusDisplayModule.kt @@ -7,12 +7,12 @@ import net.kyori.adventure.text.Component class StatusDisplayModule( handler: TextDisplayHandler, private val statusSupplier: StatusMultiblockEntity.StatusManager, - offsetLeft: Double, - offsetUp: Double, - offsetBack: Double, - scale: Float, + offsetLeft: Double = 0.0, + offsetUp: Double = STATUS_TEXT_LINE, + offsetBack: Double = 0.0, + scale: Float = MATCH_SIGN_FONT_SIZE, ) : DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { - private val updateHandler: Runnable = Runnable { display() } + private val updateHandler: Runnable = Runnable { runUpdates() } override fun register() { statusSupplier.updateManager.add(updateHandler) @@ -22,7 +22,7 @@ class StatusDisplayModule( statusSupplier.updateManager.remove(updateHandler) } - override fun getText(): Component { + override fun buildText(): Component { return statusSupplier.status } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt index 137edbb8db..814778cd0c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/ComplexFluidDisplayModule.kt @@ -16,7 +16,7 @@ class ComplexFluidDisplayModule( scale: Float ) : FluidDisplayModule(handler, container, offsetLeft, offsetUp, offsetBack, scale) { - override fun getText(): Component { + override fun buildText(): Component { return ofChildren(title, newline(), formatFluid()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt index dc79282f37..683d558a4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/FluidDisplayModule.kt @@ -18,7 +18,7 @@ abstract class FluidDisplayModule( scale: Float ) : DisplayModule(handler, offsetLeft, offsetUp, offsetBack, scale) { private val updateHandler: (InternalStorage) -> Unit = { - display() + runUpdates() } override fun register() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt index f1f6752da0..e5beb8c3b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SimpleFluidDisplayModule.kt @@ -14,7 +14,7 @@ class SimpleFluidDisplayModule( offsetBack: Double, scale: Float ) : FluidDisplayModule(handler, storage, offsetLeft, offsetUp, offsetBack, scale) { - override fun getText(): Component { + override fun buildText(): Component { return ofChildren(formatFluid(), space(), container.internalStorage.getFluidType().displayName) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt index 09d37e4021..09660f281c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/fluid/SplitFluidDisplayModule.kt @@ -14,7 +14,7 @@ class SplitFluidDisplayModule( offsetBack: Double, scale: Float ) : FluidDisplayModule(handler, storage, offsetLeft, offsetUp, offsetBack, scale) { - override fun getText(): Component { + override fun buildText(): Component { return ofChildren(container.internalStorage.getFluidType().displayName, newline(), formatFluid()) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index 9464c5ef86..094af85e3f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -3,7 +3,6 @@ package net.horizonsend.ion.server.features.custom.items import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_LIGHT_ORANGE import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren -import net.horizonsend.ion.common.utils.text.text import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.configuration.PVPBalancingConfiguration @@ -50,6 +49,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.map import net.horizonsend.ion.server.miscellaneous.utils.text.itemName import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.NamedTextColor.BLACK import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN @@ -291,9 +291,9 @@ object CustomItemRegistry : IonServerComponent() { val PROGRESS_HOLDER = register(ProgressHolder) // Starship Components Start - val BATTLECRUISER_REACTOR_CORE: CustomBlockItem = customBlockItem(identifier = "BATTLECRUISER_REACTOR_CORE", model = "starship/battlecruiser_reactor_core", displayName = text("Battlecruiser Reactor Core", BOLD), customBlock = CustomBlocks::BATTLECRUISER_REACTOR_CORE) - val BARGE_REACTOR_CORE: CustomBlockItem = customBlockItem(identifier = "BARGE_REACTOR_CORE", model = "starship/barge_reactor_core", displayName = text("Barge Reactor Core", BOLD), customBlock = CustomBlocks::BARGE_REACTOR_CORE) - val CRUISER_REACTOR_CORE: CustomBlockItem = customBlockItem(identifier = "CRUISER_REACTOR_CORE", model = "starship/cruiser_reactor_core", displayName = text("Cruiser Reactor Core", BOLD), customBlock = CustomBlocks::CRUISER_REACTOR_CORE) + val BATTLECRUISER_REACTOR_CORE: CustomBlockItem = customBlockItem(identifier = "BATTLECRUISER_REACTOR_CORE", model = "starship/battlecruiser_reactor_core", displayName = text("Battlecruiser Reactor Core", NamedTextColor.WHITE, BOLD), customBlock = CustomBlocks::BATTLECRUISER_REACTOR_CORE) + val BARGE_REACTOR_CORE: CustomBlockItem = customBlockItem(identifier = "BARGE_REACTOR_CORE", model = "starship/barge_reactor_core", displayName = text("Barge Reactor Core", NamedTextColor.WHITE, BOLD), customBlock = CustomBlocks::BARGE_REACTOR_CORE) + val CRUISER_REACTOR_CORE: CustomBlockItem = customBlockItem(identifier = "CRUISER_REACTOR_CORE", model = "starship/cruiser_reactor_core", displayName = text("Cruiser Reactor Core", NamedTextColor.WHITE, BOLD), customBlock = CustomBlocks::CRUISER_REACTOR_CORE) // Starship Components End // Gas canisters start diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index a9a784f305..c4db573d3a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -39,7 +39,7 @@ abstract class SimplePoweredEntity( protected fun standardPowerDisplay(entity: SimplePoweredEntity): TextDisplayHandler = DisplayHandlers.newMultiblockSignOverlay( entity, - { PowerEntityDisplayModule(it, entity, +0.0, +0.0, +0.0, 0.45f) } + { PowerEntityDisplayModule(it, entity) } ) override val inputsData: InputsData = InputsData.Builder(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt index b5e09be316..e0708d6513 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoPressMultiblock.kt @@ -155,8 +155,8 @@ abstract class AmmoPressMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { +abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { abstract val maxPower: Int override val description: Component get() = Component.text("Stores $maxPower power") abstract val tierMaterial: Material @@ -88,11 +84,6 @@ abstract class PowerBankMultiblock(tierText: String) : Multiblock(), EntityMulti } } - override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { - val b = getMultiblockEntity(sign) ?: return - player.information("b: ${b.powerStorage.getPower()}") - } - override fun createEntity(manager: MultiblockManager, data: PersistentMultiblockData, world: World, x: Int, y: Int, z: Int, structureDirection: BlockFace): PowerBankEntity { return PowerBankEntity(data, manager, this, x, y, z, world, structureDirection) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt index 192434c6a4..f1140ac0d8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/CarbonProcessorMultiblock.kt @@ -100,8 +100,8 @@ object CarbonProcessorMultiblock : Multiblock(), EntityMultiblock Date: Tue, 14 Jan 2025 11:38:28 -0600 Subject: [PATCH 393/500] add power metrics --- .../command/misc/TransportDebugCommand.kt | 37 ++++++++++++++++ .../modular/display/DisplayConstants.kt | 1 - .../nodes/cache/PowerTransportCache.kt | 43 ++++++++++++------- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index c984728c7a..f4b8f4b2f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -31,6 +31,8 @@ import org.bukkit.entity.Player import org.slf4j.Logger import java.lang.management.ManagementFactory import java.lang.management.ThreadInfo +import java.util.concurrent.LinkedBlockingDeque +import kotlin.system.measureNanoTime @CommandPermission("starlegacy.transportdebug") @CommandAlias("transportdebug|transportbug") @@ -194,4 +196,39 @@ object TransportDebugCommand : SLCommand() { sender.information("${destinations.size} destinations") sender.highlightBlocks(destinations.map(::toVec3i), 50L) } + + const val COLLECT_TRANSPORT_METRICS = true + + val floodFillTimes = LinkedBlockingDeque(10_000) + val solarFloodFillTimes = LinkedBlockingDeque(10_000) + val pathfindTimes = LinkedBlockingDeque(10_000) + val runTransferTimes = LinkedBlockingDeque(10_000) + val extractorTickTimes = LinkedBlockingDeque(10_000) + val solarTickTimes = LinkedBlockingDeque(10_000) + + fun measureOrFallback(metric: LinkedBlockingDeque, block: () -> T): T { + if (!COLLECT_TRANSPORT_METRICS) return block() + + if (metric.remainingCapacity() == 0) metric.removeFirst() + + var result: T + + metric.addLast(measureNanoTime { + result = block() + }) + + return result + } + + @Subcommand("metrics") + fun getMetrics(sender: Player) { + if (!COLLECT_TRANSPORT_METRICS) fail { "Transport metrics are not enabled" } + + sender.sendMessage("Flood fill average: ${floodFillTimes.average()} ns") + sender.sendMessage("Pathfind average: ${pathfindTimes.average()} ns") + sender.sendMessage("Transfer average: ${runTransferTimes.average()} ns") + sender.sendMessage("Extractor average: ${extractorTickTimes.average()} ns") + sender.sendMessage("Solar panel average: ${solarTickTimes.average()} ns") + sender.sendMessage("Solar flood average: ${solarFloodFillTimes.average()} ns") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt index 685265aad1..a47c9fbab6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayConstants.kt @@ -31,4 +31,3 @@ fun getLinePos(lineNum: Int): Double { val POWER_TEXT_LINE = getLinePos(3) val STATUS_TEXT_LINE = getLinePos(4) - diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 9104180d00..090685dbcc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.command.misc.TransportDebugCommand +import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport @@ -41,22 +43,27 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override fun tickExtractor(location: BlockKey, delta: Double) { val solarCache = holder.transportManager.solarPanelManager.cache - if (solarCache.isSolarPanel(location)) tickSolarPanel(location, delta, solarCache) + if (solarCache.isSolarPanel(location)) measureOrFallback(TransportDebugCommand.solarTickTimes) { tickSolarPanel(location, delta, solarCache) } - tickPowerExtractor(location, delta) + measureOrFallback(TransportDebugCommand.extractorTickTimes) { tickPowerExtractor(location, delta) } } private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.executor.submit { val world = holder.getWorld() val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all + println(1) // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + val destinations: List = measureOrFallback(TransportDebugCommand.floodFillTimes) { + getNetworkDestinations(location) { node -> + world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + } } + println("destinations: $destinations") if (destinations.isEmpty()) return@submit + println("was some") val transferLimit = (transportSettings().powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() val transferred = minOf(source.powerStorage.getPower(), transferLimit) @@ -64,16 +71,20 @@ class PowerTransportCache(holder: CacheHolder) : TransportC // Store this just in case val missing = source.powerStorage.removePower(transferred) - val remainder = runPowerTransfer( - Node.NodePositionData( - PowerNode.PowerExtractorNode, - world, - location, - BlockFace.SELF - ), - destinations.take(transportSettings().powerConfiguration.maxExtractorDestinations), - (transferred - missing) - ) + val remainder = measureOrFallback(TransportDebugCommand.runTransferTimes) { + runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + world, + location, + BlockFace.SELF + ), + destinations.take(transportSettings().powerConfiguration.maxExtractorDestinations), + (transferred - missing) + ) + } + + println("remainder") if (remainder > 0) { source.powerStorage.addPower(remainder) @@ -117,9 +128,9 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val numDestinations = filteredDestinations.size - val paths: Array = Array(numDestinations) { + val paths: Array = measureOrFallback(TransportDebugCommand.pathfindTimes) { Array(numDestinations) { getOrCachePath(source, filteredDestinations[it]) - } + } } var maximumResistance: Double = -1.0 From b463c771ae8d9eff7e4a16da2bc4e6947af8d943 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 15 Jan 2025 12:50:01 -0600 Subject: [PATCH 394/500] pathing fixes --- .../command/misc/TransportDebugCommand.kt | 13 ++- .../custom/items/misc/MultimeterItem.kt | 47 ++++---- .../transport/TransportConfiguration.kt | 1 + .../nodes/cache/PowerTransportCache.kt | 107 +++++++++--------- .../features/transport/nodes/types/Node.kt | 3 + .../transport/nodes/types/PowerNode.kt | 36 ++++-- .../transport/util/NodePathfinding.kt | 40 ++++--- 7 files changed, 140 insertions(+), 107 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index f4b8f4b2f5..702bcc285d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -32,6 +32,7 @@ import org.slf4j.Logger import java.lang.management.ManagementFactory import java.lang.management.ThreadInfo import java.util.concurrent.LinkedBlockingDeque +import kotlin.math.roundToInt import kotlin.system.measureNanoTime @CommandPermission("starlegacy.transportdebug") @@ -224,11 +225,11 @@ object TransportDebugCommand : SLCommand() { fun getMetrics(sender: Player) { if (!COLLECT_TRANSPORT_METRICS) fail { "Transport metrics are not enabled" } - sender.sendMessage("Flood fill average: ${floodFillTimes.average()} ns") - sender.sendMessage("Pathfind average: ${pathfindTimes.average()} ns") - sender.sendMessage("Transfer average: ${runTransferTimes.average()} ns") - sender.sendMessage("Extractor average: ${extractorTickTimes.average()} ns") - sender.sendMessage("Solar panel average: ${solarTickTimes.average()} ns") - sender.sendMessage("Solar flood average: ${solarFloodFillTimes.average()} ns") + sender.sendMessage("Flood fill average: ${floodFillTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") + sender.sendMessage("Pathfind average: ${pathfindTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") + sender.sendMessage("Transfer average: ${runTransferTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") + sender.sendMessage("Extractor average: ${extractorTickTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") + sender.sendMessage("Solar panel average: ${solarTickTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") + sender.sendMessage("Solar flood average: ${solarFloodFillTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 55f42d2fe9..06f20b1c30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.custom.items.misc -import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError +import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes @@ -37,7 +37,6 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player -import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType.INTEGER import org.bukkit.persistence.PersistentDataType.LONG @@ -46,14 +45,14 @@ import java.util.PriorityQueue object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", NamedTextColor.YELLOW), ItemFactory.unStackableCustomItem) { override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@MultimeterItem) { event, _, itemStack -> - handleSecondaryInteract(event.player, itemStack, event) + handleSecondaryInteract(event.player, itemStack) }) addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@MultimeterItem) { event, _, itemStack -> - handlePrimaryInteract(event.player, itemStack, event) + handlePrimaryInteract(event.player, itemStack) }) } - private fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { + private fun handlePrimaryInteract(livingEntity: LivingEntity, itemStack: ItemStack) { val targeted = livingEntity.getTargetBlock(null, 10) val key = toBlockKey(targeted.x, targeted.y, targeted.z) @@ -66,7 +65,7 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na tryCheckResistance(livingEntity, livingEntity.world, itemStack) } - private fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent?) { + private fun handleSecondaryInteract(livingEntity: LivingEntity, itemStack: ItemStack) { if (livingEntity !is Player) return if (livingEntity.isSneaking) { cycleNetworks(livingEntity, livingEntity.world, itemStack) @@ -115,27 +114,29 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ - private fun getIdealPath(audience: Audience, fromNode: Node.NodePositionData, toPos: BlockKey): Array? { + private fun getIdealPath(audience: Audience, fromNode: Node.NodePositionData, destination: BlockKey): Array? { // There are 2 collections here. First the priority queue contains the next nodes, which needs to be quick to iterate. val queue = PriorityQueue { o1, o2 -> o2.f.compareTo(o1.f) } // The hash set here is to speed up the .contains() check further down the road, which is slow with the queue. - val queueSet = IntOpenHashSet() + val queueSet = LongOpenHashSet() fun queueAdd(wrapper: PathfindingNodeWrapper) { + audience.information("adding $wrapper") queue.add(wrapper) - queueSet.add(wrapper.node.hashCode()) + queueSet.add(wrapper.node.position) } fun queueRemove(wrapper: PathfindingNodeWrapper) { + audience.information("removing $wrapper") queue.remove(wrapper) - queueSet.remove(wrapper.node.hashCode()) + queueSet.remove(wrapper.node.position) } queueAdd(PathfindingNodeWrapper( node = fromNode, parent = null, g = 0, - f = 0 + f = getHeuristic(fromNode, destination) )) val visited = LongOpenHashSet() @@ -143,18 +144,19 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na // Safeguard var iterations = 0L - while (queue.isNotEmpty() && iterations < 150) { + val maxDepth = ConfigurationFiles.transportSettings().powerConfiguration.maxPathfindDepth + while (queue.isNotEmpty() && iterations < maxDepth) { iterations++ val current = queue.minBy { it.f } Tasks.syncDelay(iterations) { audience.highlightBlock(toVec3i(current.node.position), 5L) } audience.information("current: ${current.node.javaClass.simpleName} at ${toVec3i(current.node.position)}") - if (current.node.position == toPos) return current.buildPath() + if (current.node.position == destination) return current.buildPath() queueRemove(current) visited.add(current.node.position) - val neighbors = getNeighbors(current, { cacheType, world, pos -> getOrCacheNode(cacheType, world, pos) },null) - if (neighbors.isEmpty()) audience.userError("Empty neighbors") + val neighbors = getNeighbors(current, { cacheType, world, pos -> getOrCacheNode(cacheType, world, pos) }, null) + audience.userError("Found ${neighbors.size} neighbors") for (newNeighbor in neighbors) { audience.information("new neighbor: $newNeighbor at ${toVec3i(newNeighbor.node.position)}") @@ -163,18 +165,21 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na continue } - newNeighbor.f = (newNeighbor.g + getHeuristic(newNeighbor, toPos)) + newNeighbor.f = (newNeighbor.g + getHeuristic(newNeighbor.node, destination)) + + if (queueSet.contains(newNeighbor.node.position)) { + audience.information("Neighbor exists in queue") + val existingNeighbor = queue.first { it.node.position == newNeighbor.node.position } - if (queueSet.contains(newNeighbor.node.hashCode())) { - audience.information("Existing in queue") - val existingNeighbor = queue.first { it.node === newNeighbor.node } if (newNeighbor.g < existingNeighbor.g) { + audience.information("New path is ideal, updating neighbor to match") + existingNeighbor.parent = newNeighbor.parent + existingNeighbor.g = newNeighbor.g existingNeighbor.f = newNeighbor.f - existingNeighbor.parent = newNeighbor.parent } } else { - audience.information("Adding to queue") + audience.information("Not present, Adding to queue") queueAdd(newNeighbor) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt index 3f5dba20ae..3541fdee8b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/TransportConfiguration.kt @@ -19,5 +19,6 @@ data class TransportConfiguration( val solarPanelTickPower: Int = 100, val maxExtractorDestinations: Int = 100, val maxSolarDestinations: Int = 100, + val maxPathfindDepth: Int = 600 ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 090685dbcc..94b2d6da4a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -34,8 +34,8 @@ class PowerTransportCache(holder: CacheHolder) : TransportC .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) .addSimpleNode(SPONGE, PowerNode.SpongeNode) .addDataHandler(END_ROD) { data, _ -> PowerNode.EndRodNode(data.facing.axis) } - .addSimpleNode(REDSTONE_BLOCK, PowerNode.PowerMergeNode) - .addSimpleNode(IRON_BLOCK, PowerNode.PowerMergeNode) + .addSimpleNode(REDSTONE_BLOCK, PowerNode.RedstoneMergeNode) + .addSimpleNode(IRON_BLOCK, PowerNode.IronMergeNode) .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(this, data.facing, holder.getWorld(), loc) } .addSimpleNode(NOTE_BLOCK, PowerInputNode) @@ -43,75 +43,74 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override fun tickExtractor(location: BlockKey, delta: Double) { val solarCache = holder.transportManager.solarPanelManager.cache - if (solarCache.isSolarPanel(location)) measureOrFallback(TransportDebugCommand.solarTickTimes) { tickSolarPanel(location, delta, solarCache) } + if (solarCache.isSolarPanel(location)) tickSolarPanel(location, delta, solarCache) - measureOrFallback(TransportDebugCommand.extractorTickTimes) { tickPowerExtractor(location, delta) } + tickPowerExtractor(location, delta) } private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.executor.submit { - val world = holder.getWorld() - val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } - val source = sources.randomOrNull() ?: return@submit //TODO take from all - println(1) - - // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = measureOrFallback(TransportDebugCommand.floodFillTimes) { - getNetworkDestinations(location) { node -> - world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + measureOrFallback(TransportDebugCommand.extractorTickTimes) { + val world = holder.getWorld() + val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } + val source = sources.randomOrNull() ?: return@measureOrFallback //TODO take from all + + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = measureOrFallback(TransportDebugCommand.floodFillTimes) { + getNetworkDestinations(location) { node -> + world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + } + } + + if (destinations.isEmpty()) return@measureOrFallback + + val transferLimit = (transportSettings().powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() + val transferred = minOf(source.powerStorage.getPower(), transferLimit) + + // Store this just in case + val missing = source.powerStorage.removePower(transferred) + + val remainder = measureOrFallback(TransportDebugCommand.runTransferTimes) { + runPowerTransfer( + Node.NodePositionData( + PowerNode.PowerExtractorNode, + world, + location, + BlockFace.SELF + ), + destinations.take(transportSettings().powerConfiguration.maxExtractorDestinations), + (transferred - missing) + ) + } + + if (remainder > 0) { + source.powerStorage.addPower(remainder) } } - println("destinations: $destinations") + } - if (destinations.isEmpty()) return@submit - println("was some") + private fun tickSolarPanel(location: BlockKey, delta: Double, solarCache: SolarPanelCache) = NewTransport.executor.submit { + measureOrFallback(TransportDebugCommand.solarTickTimes) { + val transportPower = solarCache.getPower(holder.getWorld(), location, delta) + if (transportPower == 0) return@measureOrFallback - val transferLimit = (transportSettings().powerConfiguration.maxPowerRemovedPerExtractorTick * delta).roundToInt() - val transferred = minOf(source.powerStorage.getPower(), transferLimit) + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power + val destinations: List = getNetworkDestinations(location) { node -> + holder.getWorld().ion.inputManager.getHolders(CacheType.POWER, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + } - // Store this just in case - val missing = source.powerStorage.removePower(transferred) + if (destinations.isEmpty()) return@measureOrFallback - val remainder = measureOrFallback(TransportDebugCommand.runTransferTimes) { - runPowerTransfer( + holder.transportManager.powerNodeManager.cache.runPowerTransfer( Node.NodePositionData( PowerNode.PowerExtractorNode, - world, + holder.getWorld(), location, BlockFace.SELF ), - destinations.take(transportSettings().powerConfiguration.maxExtractorDestinations), - (transferred - missing) + destinations.take(transportSettings().powerConfiguration.maxSolarDestinations), + transportPower ) } - - println("remainder") - - if (remainder > 0) { - source.powerStorage.addPower(remainder) - } - } - - private fun tickSolarPanel(location: BlockKey, delta: Double, solarCache: SolarPanelCache) = NewTransport.executor.submit { - val transportPower = solarCache.getPower(holder.getWorld(), location, delta) - if (transportPower == 0) return@submit - - // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - holder.getWorld().ion.inputManager.getHolders(CacheType.POWER, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } - } - - if (destinations.isEmpty()) return@submit - - holder.transportManager.powerNodeManager.cache.runPowerTransfer( - Node.NodePositionData( - PowerNode.PowerExtractorNode, - holder.getWorld(), - location, - BlockFace.SELF - ), - destinations.take(transportSettings().powerConfiguration.maxSolarDestinations), - transportPower - ) } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt index 5a4af8e96e..eb4f098d40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt @@ -46,6 +46,9 @@ interface Node { return filterPositionData(nodes, backwards) } + /** + * Filters the found adjacent nodes, after checking for transport possibility + **/ fun filterPositionData(nextNodes: List, backwards: BlockFace): List = nextNodes data class NodePositionData(val type: Node, val world: World, val position: BlockKey, val offset: BlockFace) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 3a1555445a..a75413adaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.client.display.modular.display.FlowMe import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -56,26 +57,41 @@ sealed interface PowerNode : Node { fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.POWER, location).filterIsInstance() } - data object PowerMergeNode : PowerNode { - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is SpongeNode - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is SpongeNode + interface MergeNode { + fun mergeNodeTransferCheck(other: Node) = if (other is MergeNode) other.javaClass == javaClass else true + } + + sealed interface PowerMergeNode : PowerNode, MergeNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is SpongeNode && mergeNodeTransferCheck(other) override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { + override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { val forward = backwards.oppositeFace - nextNodes.firstOrNull { it.offset == forward }?.let { return listOf(it) } + + for (node in nextNodes) { + if (node.offset == forward) return listOf(node) + } + return nextNodes } } - data object PowerInvertedMergeNode : PowerNode { + data object RedstoneMergeNode : PowerMergeNode { + override val pathfindingResistance: Double = 0.5 + } + + data object IronMergeNode : PowerMergeNode { + override val pathfindingResistance: Double = 0.5 + } + + data object PowerInvertedMergeNode : PowerNode, MergeNode { override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other is EndRodNode - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is EndRodNode + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is EndRodNode && mergeNodeTransferCheck(other) override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { + override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { val forward = backwards.oppositeFace nextNodes.firstOrNull { it.offset == forward }?.let { return listOf(it) } return nextNodes diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 47f0502de7..c7dba27077 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.util import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -23,7 +24,7 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { **/ fun getIdealPath( from: Node.NodePositionData, - to: BlockKey, + destination: BlockKey, cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null ): Array? { @@ -46,7 +47,7 @@ fun getIdealPath( node = from, parent = null, g = 0, - f = 0 + f = getHeuristic(from, destination) )) val visited = IntOpenHashSet() @@ -54,28 +55,34 @@ fun getIdealPath( // Safeguard var iterations = 0 - while (queue.isNotEmpty() && iterations < 150) { + val maxDepth = ConfigurationFiles.transportSettings().powerConfiguration.maxPathfindDepth + while (queue.isNotEmpty() && iterations < maxDepth) { iterations++ val current = queue.minBy { it.f } - if (current.node.position == to) return current.buildPath() + if (current.node.position == destination) return current.buildPath() queueRemove(current) visited.add(current.node.hashCode()) - for (neighbor in getNeighbors(current, cachedNodeProvider, pathfindingFilter)) { - if (visited.contains(neighbor.node.hashCode())) continue - neighbor.f = (neighbor.g + getHeuristic(neighbor, to)) + // Compute new neighbor data from current position + for (computedNeighbor in getNeighbors(current, cachedNodeProvider, pathfindingFilter)) { + if (visited.contains(computedNeighbor.node.hashCode())) continue - if (queueSet.contains(neighbor.node.position)) { - val existingNeighbor = queue.first { it.node === neighbor.node } + // Update the f value + computedNeighbor.f = (computedNeighbor.g + getHeuristic(computedNeighbor.node, destination)) - if (neighbor.g < existingNeighbor.g) { - existingNeighbor.g = neighbor.g - existingNeighbor.parent = neighbor.parent + if (queueSet.contains(computedNeighbor.node.position)) { + val existingNeighbor = queue.first { it.node.position == computedNeighbor.node.position } + + if (computedNeighbor.g < existingNeighbor.g) { + existingNeighbor.parent = computedNeighbor.parent + + existingNeighbor.g = computedNeighbor.g + existingNeighbor.f = computedNeighbor.f } } else { - queueAdd(neighbor) + queueAdd(computedNeighbor) } } } @@ -105,9 +112,9 @@ fun getNeighbors( // The heuristic used for the algorithm in this case is the distance from the node to the destination, which is typical, // But it also includes the pathfinding resistance to try to find the least resistant path. -fun getHeuristic(wrapper: PathfindingNodeWrapper, destination: BlockKey): Int { - val resistance = wrapper.node.type.pathfindingResistance - return (toVec3i(wrapper.node.position).distance(toVec3i(destination)) + resistance).roundToInt() +fun getHeuristic(node: Node.NodePositionData, destination: BlockKey): Int { + val resistance = node.type.pathfindingResistance + return (toVec3i(node.position).distance(toVec3i(destination)) + resistance).roundToInt() } /** @@ -163,3 +170,4 @@ data class PathfindingNodeWrapper( fun calculatePathResistance(path: Array): Double { return path.sumOf { it.type.pathfindingResistance } } + From 6f2404ab387f048ac804dd83b5154086e313ab68 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 15 Jan 2025 13:10:06 -0600 Subject: [PATCH 395/500] prioritize input nodes in addition to forward --- .../nodes/cache/PowerTransportCache.kt | 2 +- .../transport/nodes/types/PowerNode.kt | 42 +++++++++---------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 94b2d6da4a..ce03014ca8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -36,7 +36,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC .addDataHandler(END_ROD) { data, _ -> PowerNode.EndRodNode(data.facing.axis) } .addSimpleNode(REDSTONE_BLOCK, PowerNode.RedstoneMergeNode) .addSimpleNode(IRON_BLOCK, PowerNode.IronMergeNode) - .addSimpleNode(LAPIS_BLOCK, PowerNode.PowerInvertedMergeNode) + .addSimpleNode(LAPIS_BLOCK, PowerNode.InvertedMergeNode) .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(this, data.facing, holder.getWorld(), loc) } .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index a75413adaf..c8bc68df33 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -57,45 +57,43 @@ sealed interface PowerNode : Node { fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.POWER, location).filterIsInstance() } - interface MergeNode { - fun mergeNodeTransferCheck(other: Node) = if (other is MergeNode) other.javaClass == javaClass else true - } - - sealed interface PowerMergeNode : PowerNode, MergeNode { - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is SpongeNode && mergeNodeTransferCheck(other) - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + interface MergeNode : PowerNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { val forward = backwards.oppositeFace + val filtered = mutableListOf() for (node in nextNodes) { - if (node.offset == forward) return listOf(node) + if (node.offset == forward) filtered.add(node) + if (node.type is PowerInputNode) filtered.add(node) } + if (filtered.isNotEmpty()) return filtered + return nextNodes } + + /** Check common to all merge nodes, stops transfer between different types thereof */ + fun mergeNodeTransferCheck(other: Node) = if (other is MergeNode) other.javaClass == javaClass else true + } + + sealed interface StandardMergeNode : MergeNode { + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is SpongeNode && mergeNodeTransferCheck(other) } - data object RedstoneMergeNode : PowerMergeNode { + data object RedstoneMergeNode : StandardMergeNode { override val pathfindingResistance: Double = 0.5 } - data object IronMergeNode : PowerMergeNode { + data object IronMergeNode : StandardMergeNode { override val pathfindingResistance: Double = 0.5 } - data object PowerInvertedMergeNode : PowerNode, MergeNode { - override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is EndRodNode && mergeNodeTransferCheck(other) - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - - override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { - val forward = backwards.oppositeFace - nextNodes.firstOrNull { it.offset == forward }?.let { return listOf(it) } - return nextNodes - } + data object InvertedMergeNode : PowerNode, MergeNode { + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is EndRodNode && mergeNodeTransferCheck(other) + override val pathfindingResistance: Double = 0.5 } data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, var world: World, var location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { From 0274481d302a233bc59a196cc55c446f261576a3 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 15 Jan 2025 14:31:43 -0600 Subject: [PATCH 396/500] Fix initialization order problem with power flow meter --- .../client/display/modular/DisplayHandlers.kt | 2 +- .../transport/nodes/types/PowerNode.kt | 54 +++++++------------ 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt index 8fccfc833b..3ea4139685 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/DisplayHandlers.kt @@ -30,7 +30,7 @@ object DisplayHandlers : IonServerComponent() { fun newBlockOverlay(holder: DisplayHandlerHolder, block: Vec3i, direction: BlockFace, vararg displayModule: (TextDisplayHandler) -> DisplayModule): TextDisplayHandler { val builder = TextDisplayHandler.builder(holder, block.x, block.y, block.z) - .setOffset(offsetRight = 0.0, offsetUp = -0.1, offsetForward = -0.39) + .setOffset(offsetRight = 0.0, offsetUp = -0.1, offsetForward = +0.501) .setDirection(direction) displayModule.forEach(builder::addDisplay) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index c8bc68df33..916533b197 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -97,56 +97,39 @@ sealed interface PowerNode : Node { } data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, var world: World, var location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { - override var isAlive: Boolean = true + /** Data entry of transferred power, contains the amount and the timestamp if the transfer */ + private data class TransferredPower(val transferred: Int, val time: Long = System.currentTimeMillis()) - override fun handlerGetWorld(): World { - return world - } + // Use array deque as a stack + private val averages = ArrayDeque(NUMBER_STORED_AVERAGES) - val displayHandler = DisplayHandlers.newBlockOverlay( - this, - toVec3i(location), - face, - { FlowMeterDisplayModule(it, this, 0.0, 0.0, 0.0, 0.7f) } - ).register() + override var isAlive: Boolean = true - private val STORED_AVERAGES = 20 - private val averages = mutableListOf() + val displayHandler = DisplayHandlers.newBlockOverlay(this, toVec3i(location), face, { FlowMeterDisplayModule(it, this, 0.0, 0.0, 0.0, 0.7f) }) fun onCompleteChain(transferred: Int) { - addTransferred(TransferredPower(transferred, System.currentTimeMillis())) - displayHandler.update() - } - - private fun addTransferred(transferredSnapshot: TransferredPower) { - val currentSize = averages.size - - if (currentSize < STORED_AVERAGES) { - averages.add(transferredSnapshot) - return - } + // Push onto queue + if (averages.size == NUMBER_STORED_AVERAGES) averages.removeFirst() + averages.addLast(TransferredPower(transferred)) - // If it is full, shift all averages to the right - for (index in 18 downTo 0) { - averages[index + 1] = averages[index] - } - - averages[0] = transferredSnapshot + displayHandler.update() } private fun calculateAverage(): Double { - val sum = averages.sumOf { it.transferred } + val nonNull = averages.filterNotNull() + val sum = nonNull.sumOf { it.transferred } - val timeDiff = (System.currentTimeMillis() - averages.minOf { it.time }) / 1000.0 + val timeDiff = (System.currentTimeMillis() - nonNull.minOf { it.time }) / 1000.0 return sum / timeDiff } fun formatFlow(): Component { + val nonNull = averages.filterNotNull() var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) // If no averages, or no power has been moved in 5 seconds, go to 0 - if (averages.isEmpty() || System.currentTimeMillis() - averages.maxOf { it.time } > 5000) { + if (averages.isEmpty() || System.currentTimeMillis() - nonNull.maxOf { it.time } > 5000) { avg = 0.0 } @@ -170,6 +153,9 @@ sealed interface PowerNode : Node { displayHandler.displace(movement) } - private data class TransferredPower(val transferred: Int, val time: Long) - } + override fun handlerGetWorld(): World = world + + + companion object { private const val NUMBER_STORED_AVERAGES = 20 } + } } From fc51dff78f6e35c31a937f194af8558838a0657f Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Wed, 15 Jan 2025 23:59:46 -0600 Subject: [PATCH 397/500] start of (attempt 4) permanent multiblock recipe system --- .../crafting/recipe/take2/IndustryRecipe.kt | 4 -- .../recipe/take2/LegacyIndustryRecipe.kt | 51 ------------------- .../crafting/recipe/take2/NewRecipe.kt | 22 -------- .../recipe/take2/ingredient/ItemIngredient.kt | 14 ----- .../ingredient/MultiblockRecipeIngredient.kt | 8 --- .../take2/ingredient/PowerIngredient.kt | 14 ----- .../take2/ingredient/ResourceIngredient.kt | 3 -- .../recipe/take2/result/FluidResult.kt | 5 -- .../recipe/take2/result/ItemResult.kt | 7 --- .../take2/result/MultiblockRecipeResult.kt | 5 -- .../entity/type/ProgressMultiblock.kt | 2 + .../type/RecipeProcessingMultiblockEntity.kt | 11 ++++ .../newcrafting/MultiblockRecipeRegistry.kt | 22 ++++++++ .../newcrafting/input/BuildableRecipeInput.kt | 15 ++++++ .../DoubleIndustryMultiblockEnviornment.kt | 39 ++++++++++++++ .../input/IndustryMultiblockEnviornment.kt | 34 +++++++++++++ .../input/MultiblockRecipeEnviornment.kt | 10 ++++ .../recipe/IndustryMultiblockRecipe.kt | 34 +++++++++++++ .../newcrafting/recipe/NewMultiblockRecipe.kt | 22 ++++++++ .../recipe/requirement/ItemRequirement.kt | 44 ++++++++++++++++ .../recipe/requirement/PowerRequirement.kt | 7 +++ .../recipe/requirement/RecipeRequirement.kt | 5 ++ .../recipe/requirement/RequirementHolder.kt | 10 ++++ .../newcrafting/recipe/result/RecipeResult.kt | 8 +++ .../miscellaneous/registrations/Components.kt | 2 + 25 files changed, 265 insertions(+), 133 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt deleted file mode 100644 index 298939da27..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/IndustryRecipe.kt +++ /dev/null @@ -1,4 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2 - -class IndustryRecipe { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt deleted file mode 100644 index 7332a8a2d3..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/LegacyIndustryRecipe.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2 - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient.ResourceIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result.FluidResult -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result.ItemResult -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result.MultiblockRecipeResult -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import org.bukkit.inventory.FurnaceInventory -import kotlin.reflect.KClass - -class LegacyIndustryRecipe( - entity: KClass, - private val result: MultiblockRecipeResult, - private val smelting: MultiblockRecipeIngredient?, - private val fuel: MultiblockRecipeIngredient?, - private vararg val resources: ResourceIngredient, -) : NewRecipe(entity) { - - private fun getFurnace(context: ExecutionContext): FurnaceInventory { - return context.entity.getInventory(0, 0, 0) as? FurnaceInventory ?: throw IllegalStateException("Multiblock integrity should be ensured before execution") - } - - override fun checkResourcesAvailable(context: ExecutionContext): Boolean { - if (smelting?.check(context) == false) return false - if (fuel?.check(context) == false) return false - return resources.all { it.check(context) } - } - - override fun checkSpaceAvailable(context: ExecutionContext): Boolean { - val furnace = getFurnace(context) - - return when (result) { - is ItemResult -> { - val resultSlot = furnace.result ?: return true - val resultItem = result.assemble() - if (resultSlot.isSimilar(resultItem)) return false - if (resultItem.amount + resultSlot.amount > resultSlot.maxStackSize) return false - true - } - is FluidResult -> context.entity is FluidStoringEntity && context.entity.getCapacityFor(result.fluid.type) >= result.fluid.amount - else -> false - } - } - - override fun execute(context: ExecutionContext) { - val furnace = getFurnace(context) - - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt deleted file mode 100644 index 241545488a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/NewRecipe.kt +++ /dev/null @@ -1,22 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2 - -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.minecraft.commands.execution.ExecutionContext -import kotlin.reflect.KClass - -abstract class NewRecipe(val multiblockEntity: KClass) { - abstract fun checkSpaceAvailable(context: ExecutionContext): Boolean - - abstract fun checkResourcesAvailable(context: ExecutionContext): Boolean - - fun checkExecution(context: ExecutionContext): Boolean { - if (!checkResourcesAvailable(context)) return false - if (!checkSpaceAvailable(context)) return false - //TODO - return true - } - - abstract fun execute(context: ExecutionContext) - - class ExecutionContext(val entity: MultiblockEntity) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt deleted file mode 100644 index 75c8b48c7b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ItemIngredient.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.NewRecipe -import org.bukkit.inventory.ItemStack - -class ItemIngredient(private val item: ItemStack) : MultiblockRecipeIngredient() { - override fun check(context: NewRecipe.ExecutionContext): Boolean { - return true - } - - override fun consume(context: NewRecipe.ExecutionContext) { - - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt deleted file mode 100644 index 0b9d9324f1..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/MultiblockRecipeIngredient.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.NewRecipe - -abstract class MultiblockRecipeIngredient { - abstract fun consume(context: NewRecipe.ExecutionContext) - abstract fun check(context: NewRecipe.ExecutionContext): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt deleted file mode 100644 index cea15e5935..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/PowerIngredient.kt +++ /dev/null @@ -1,14 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.NewRecipe -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity - -class PowerIngredient(private val amount: Int) : ResourceIngredient() { - override fun check(context: NewRecipe.ExecutionContext): Boolean { - return context.entity is PoweredMultiblockEntity && context.entity.powerStorage.canRemovePower(amount) - } - - override fun consume(context: NewRecipe.ExecutionContext) { - (context.entity as PoweredMultiblockEntity).powerStorage.removePower(amount) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt deleted file mode 100644 index 2eec28b02a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/ingredient/ResourceIngredient.kt +++ /dev/null @@ -1,3 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.ingredient - -abstract class ResourceIngredient : MultiblockRecipeIngredient() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt deleted file mode 100644 index 27cf325691..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/FluidResult.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result - -import net.horizonsend.ion.server.features.transport.fluids.FluidStack - -class FluidResult(val fluid: FluidStack) : MultiblockRecipeResult() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt deleted file mode 100644 index 42a51213a2..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/ItemResult.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result - -import org.bukkit.inventory.ItemStack - -class ItemResult(private val item: ItemStack) : MultiblockRecipeResult() { - fun assemble(): ItemStack = item.clone() -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt deleted file mode 100644 index 1d11bc1e95..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/take2/result/MultiblockRecipeResult.kt +++ /dev/null @@ -1,5 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe.take2.result - -abstract class MultiblockRecipeResult { -// abstract fun assemble() -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 3526f332d3..00a29fee31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -27,6 +27,8 @@ interface ProgressMultiblock { var lastProgressTick: Long = data.getAdditionalDataOrDefault(LAST_PROGRESS_TICK, LONG, System.currentTimeMillis()) private var currentProgress: Double = data.getAdditionalDataOrDefault(PROGRESS, DOUBLE, 0.0) + fun getCurrentProgress(): Double = currentProgress + /** * Increments progress with a percentage of a total duration. * Returns whether the progress has reached 100% diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt new file mode 100644 index 0000000000..73fbc66545 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment + +interface RecipeProcessingMultiblockEntity { + fun buildInput(): Input + + fun getRecipesFor() { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt new file mode 100644 index 0000000000..14e9e2af25 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -0,0 +1,22 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting + +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf +import kotlin.reflect.KClass + +object MultiblockRecipeRegistry : IonServerComponent() { + val recipes = mutableListOf>() + val byMultiblock = multimapOf>, NewMultiblockRecipe<*>>() + + + + fun > register(recipe: R): R { + recipes.add(recipe) + byMultiblock[recipe.entityType].add(recipe) + + return recipe + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt new file mode 100644 index 0000000000..3022f5fe9a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt @@ -0,0 +1,15 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.input + +class BuildableRecipeInput { + + + companion object { + fun builder(): Builder = Builder() + } + + class Builder() { + fun build(): BuildableRecipeInput { + return BuildableRecipeInput() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt new file mode 100644 index 0000000000..777a9789ce --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt @@ -0,0 +1,39 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.input + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.inventory.ItemStack + +class DoubleIndustryMultiblockEnviornment( + val furnaceInventory: FurnaceInventory, + val powerStorage: PowerStorage, + val tickingManager: TickedMultiblockEntityParent.TickingManager, + val progressManager: ProgressMultiblock.ProgressManager +) : MultiblockRecipeEnviornment { + constructor(entity: MultiblockEntity) : this( + entity.getInventory(0, 0, 0) as FurnaceInventory, + (entity as PoweredMultiblockEntity).powerStorage, + (entity as TickedMultiblockEntityParent).tickingManager, + (entity as ProgressMultiblock).progressManager + ) + + fun getProcessedItem(): ItemStack? = furnaceInventory.smelting + fun getProgress(): Double = progressManager.getCurrentProgress() + + override fun getItemSize(): Int = 2 + override fun getItem(index: Int): ItemStack? { + return when (index) { + 1 -> furnaceInventory.smelting + 2 -> furnaceInventory.fuel + else -> throw IndexOutOfBoundsException() + } + } + + override fun isEmpty(): Boolean { + return furnaceInventory.smelting == null && furnaceInventory.fuel == null + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt new file mode 100644 index 0000000000..6ff8b91e6c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.input + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.inventory.ItemStack + +class IndustryMultiblockEnviornment( + val furnaceInventory: FurnaceInventory, + val powerStorage: PowerStorage, + val tickingManager: TickedMultiblockEntityParent.TickingManager, + val progressManager: ProgressMultiblock.ProgressManager +) : MultiblockRecipeEnviornment { + constructor(entity: MultiblockEntity) : this( + entity.getInventory(0, 0, 0) as FurnaceInventory, + (entity as PoweredMultiblockEntity).powerStorage, + (entity as TickedMultiblockEntityParent).tickingManager, + (entity as ProgressMultiblock).progressManager + ) + + fun getProgress(): Double = progressManager.getCurrentProgress() + + override fun getItemSize(): Int = 1 + override fun getItem(index: Int): ItemStack? { + return furnaceInventory.smelting + } + + override fun isEmpty(): Boolean { + return furnaceInventory.smelting != null + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt new file mode 100644 index 0000000000..6a8835ed96 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.input + +import org.bukkit.inventory.ItemStack + +interface MultiblockRecipeEnviornment { + fun getItemSize(): Int + fun getItem(index: Int): ItemStack? + + fun isEmpty(): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt new file mode 100644 index 0000000000..61771ad5bb --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt @@ -0,0 +1,34 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe + +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.IndustryMultiblockEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.RecipeResult +import kotlin.reflect.KClass + +/** + * A multiblock recipe that uses a furnace inventory. + * + * @param smeltingItem Requirement for the item in the top slot. If it is null, there will be a requirement for this slot to be empty. + * @param fuelitem Requirement for the item in the bottom slot. If it is null, there will be a requirement for this slot to be empty. + **/ +class IndustryMultiblockRecipe( + clazz: KClass>, + smeltingItem: ItemRequirement?, + fuelitem: ItemRequirement?, + power: PowerRequirement, + val result: RecipeResult +) : NewMultiblockRecipe(clazz) { + + override val requirements: Collection> = listOf( + RequirementHolder({ it.getItem(0) }, smeltingItem ?: ItemRequirement.empty()), + RequirementHolder({ it.getItem(1) }, fuelitem ?: ItemRequirement.empty()), + RequirementHolder({ it.powerStorage.getPower() }, power) + ) + + override fun assemble(input: IndustryMultiblockEnviornment): RecipeResult { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt new file mode 100644 index 0000000000..dfb2936fb5 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt @@ -0,0 +1,22 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe + +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.RecipeResult +import org.bukkit.inventory.ItemStack +import kotlin.reflect.KClass + +abstract class NewMultiblockRecipe(val entityType: KClass>) { + protected abstract val requirements: Collection> + + fun getItemRequirements(): Collection> = requirements.filter { + + } + + fun getAllRequirements(): Collection> = requirements + + fun ensureRequirementsAvailable(input: E): Boolean + + abstract fun assemble(input: E): RecipeResult +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt new file mode 100644 index 0000000000..335fef17f4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt @@ -0,0 +1,44 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement + +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import org.bukkit.Material +import org.bukkit.inventory.ItemStack + +fun interface ItemRequirement : RecipeRequirement { + override fun ensureAvailable(resource: ItemStack?): Boolean { + return matches(resource) + } + + fun matches(item: ItemStack?): Boolean + + fun consume(item: ItemStack) { + item.amount-- + } + + class CustomItemRequirement(val customItem: CustomItem) : ItemRequirement { + override fun matches(item: ItemStack?): Boolean { + return item?.customItem == customItem && item.amount >= 1 + } + } + + class MaterialRequirement(val material: Material) : ItemRequirement { + override fun matches(item: ItemStack?): Boolean { + return item?.type == material && item.amount >= 1 + } + } + + class ItemStackRequirement(val itemStack: ItemStack) : ItemRequirement { + override fun matches(item: ItemStack?): Boolean { + return item != null && itemStack.isSimilar(item) && item.amount >= 1 + } + } + + companion object { + /** Gets an item requirement that requires a slot to be empty */ + fun empty() = ItemRequirement { + if (it == null) return@ItemRequirement true + it.isEmpty + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt new file mode 100644 index 0000000000..685aa60e93 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement + +class PowerRequirement(val amount: Int) : RecipeRequirement { + override fun ensureAvailable(resource: Int): Boolean { + return resource >= amount + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt new file mode 100644 index 0000000000..e2e7e8f1f0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement + +interface RecipeRequirement { + fun ensureAvailable(resource: T): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt new file mode 100644 index 0000000000..144ca5b31f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment + +class RequirementHolder(val getter: (T) -> V, val requirement: RecipeRequirement) { + fun checkRequirement(enviornment: T): Boolean { + val resourceValue = getter.invoke(enviornment) + return requirement.ensureAvailable(resourceValue) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt new file mode 100644 index 0000000000..9e51a27e4e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment + +interface RecipeResult { + fun verifySpace(input: Input) + fun execute(input: Input) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 7cce13b108..68ca21dcf4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -43,6 +43,7 @@ import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes +import net.horizonsend.ion.server.features.multiblock.newcrafting.MultiblockRecipeRegistry import net.horizonsend.ion.server.features.nations.NationsBalancing import net.horizonsend.ion.server.features.nations.NationsMap import net.horizonsend.ion.server.features.nations.NationsMasterTasks @@ -234,4 +235,5 @@ val components: List = listOf( DisplayHandlers, PlanetTeleportCooldown, MultiBlockDisplay, + MultiblockRecipeRegistry, ) From ac4ff348c932baf7e719cc6d010924aa28e1080d Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 16 Jan 2025 00:29:06 -0600 Subject: [PATCH 398/500] work on the base recipe class --- .../newcrafting/recipe/IndustryMultiblockRecipe.kt | 11 +++++++---- .../newcrafting/recipe/NewMultiblockRecipe.kt | 9 +++++---- .../recipe/requirement/RequirementHolder.kt | 9 ++++++++- .../newcrafting/recipe/result/RecipeResult.kt | 6 +++--- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt index 61771ad5bb..c466b21b99 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt @@ -23,12 +23,15 @@ class IndustryMultiblockRecipe( ) : NewMultiblockRecipe(clazz) { override val requirements: Collection> = listOf( - RequirementHolder({ it.getItem(0) }, smeltingItem ?: ItemRequirement.empty()), - RequirementHolder({ it.getItem(1) }, fuelitem ?: ItemRequirement.empty()), - RequirementHolder({ it.powerStorage.getPower() }, power) + RequirementHolder.of({ it.getItem(0) }, smeltingItem ?: ItemRequirement.empty()), + RequirementHolder.of({ it.getItem(1) }, fuelitem ?: ItemRequirement.empty()), + RequirementHolder.of({ it.powerStorage.getPower() }, power) ) - override fun assemble(input: IndustryMultiblockEnviornment): RecipeResult { + override fun assemble(enviornment: IndustryMultiblockEnviornment) { + if (!verifyAllRequirements(enviornment)) result + if (result.verifySpace(enviornment)) return + result.execute(enviornment) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt index dfb2936fb5..6cd5aff8b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt @@ -3,20 +3,21 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.RecipeResult import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass abstract class NewMultiblockRecipe(val entityType: KClass>) { protected abstract val requirements: Collection> - fun getItemRequirements(): Collection> = requirements.filter { + fun getItemRequirements(): Collection> = requirements + .filter { it.dataTypeClass == ItemStack::class.java } + .filterIsInstance>() - } + fun verifyAllRequirements(enviornment: E): Boolean = getAllRequirements().all { holder -> holder.checkRequirement(enviornment) } fun getAllRequirements(): Collection> = requirements fun ensureRequirementsAvailable(input: E): Boolean - abstract fun assemble(input: E): RecipeResult + abstract fun assemble(input: E) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt index 144ca5b31f..de20932ca5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt @@ -2,9 +2,16 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requir import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment -class RequirementHolder(val getter: (T) -> V, val requirement: RecipeRequirement) { +class RequirementHolder(val dataTypeClass: Class, val getter: (T) -> V, val requirement: RecipeRequirement) { fun checkRequirement(enviornment: T): Boolean { val resourceValue = getter.invoke(enviornment) return requirement.ensureAvailable(resourceValue) } + + companion object { + inline fun of( + noinline getter: (T) -> V, + requirement: RecipeRequirement + ): RequirementHolder = RequirementHolder(V::class.java, getter, requirement) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt index 9e51a27e4e..d1fd086bb2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment -interface RecipeResult { - fun verifySpace(input: Input) - fun execute(input: Input) +interface RecipeResult { + fun verifySpace(input: E): Boolean + fun execute(input: E) } From 4a2f58864a6d0ce2954b6f1c4ac2359cd1c27670 Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 16 Jan 2025 01:34:21 -0600 Subject: [PATCH 399/500] probably everything I need to migrate recipes over --- .../entity/type/ProgressMultiblock.kt | 14 ++++--- .../type/RecipeProcessingMultiblockEntity.kt | 24 ++++++++++-- .../newcrafting/MultiblockRecipeRegistry.kt | 9 ++++- .../newcrafting/input/BuildableRecipeInput.kt | 15 ------- .../DoubleIndustryMultiblockEnviornment.kt | 39 ------------------- ...ckEnviornment.kt => FurnaceEnviornment.kt} | 4 +- ...ipeEnviornment.kt => RecipeEnviornment.kt} | 2 +- ...ckRecipe.kt => FurnaceMultiblockRecipe.kt} | 15 +++---- .../newcrafting/recipe/NewMultiblockRecipe.kt | 6 +-- .../recipe/requirement/RequirementHolder.kt | 6 +-- .../recipe/result/ProgressResult.kt | 29 ++++++++++++++ .../newcrafting/recipe/result/RecipeResult.kt | 4 +- 12 files changed, 82 insertions(+), 85 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/{IndustryMultiblockEnviornment.kt => FurnaceEnviornment.kt} (94%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/{MultiblockRecipeEnviornment.kt => RecipeEnviornment.kt} (83%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/{IndustryMultiblockRecipe.kt => FurnaceMultiblockRecipe.kt} (76%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 00a29fee31..479117c1f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -16,11 +16,7 @@ import java.time.Duration interface ProgressMultiblock { val progressManager: ProgressManager fun tickProgress(totalDuration: Duration): Boolean { - val current = System.currentTimeMillis() - val delta = Duration.ofMillis(current - progressManager.lastProgressTick) - - progressManager.lastProgressTick = current - return progressManager.addProgress(totalDuration, delta) + return progressManager.addProgress(totalDuration) } class ProgressManager(data: PersistentMultiblockData) { @@ -33,7 +29,13 @@ interface ProgressMultiblock { * Increments progress with a percentage of a total duration. * Returns whether the progress has reached 100% **/ - fun addProgress(totalDuration: Duration, delta: Duration): Boolean { + fun addProgress(totalDuration: Duration): Boolean { + val now = System.currentTimeMillis() + val deltaMillis = now - lastProgressTick + val delta = Duration.ofMillis(deltaMillis) + + lastProgressTick = now + // Convert the delta to a percentage of the total duration, and add that percentage val additionalPercent = totalDuration.toMillis().toDouble() / delta.toMillis().toDouble() currentProgress += additionalPercent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt index 73fbc66545..8b9dca6336 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt @@ -1,11 +1,27 @@ package net.horizonsend.ion.server.features.multiblock.entity.type -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.newcrafting.MultiblockRecipeRegistry +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe -interface RecipeProcessingMultiblockEntity { - fun buildInput(): Input +interface RecipeProcessingMultiblockEntity { + fun buildRecipeEnviornment(): E - fun getRecipesFor() { + fun getRecipesFor(): NewMultiblockRecipe? { + val enviornment = buildRecipeEnviornment() + val recipes = MultiblockRecipeRegistry.getRecipesFor(this) + val match = recipes.filter { recipe -> recipe.verifyAllRequirements(enviornment) } + if (match.size > 1) IonServer.slF4JLogger.warn("Multiple recipes match input! This should not happen!!! Infringing recipes: ${match.joinToString { it.identifier }}") + + return match.firstOrNull() + } + + fun tryProcessRecipe(): Boolean { + val enviornment = buildRecipeEnviornment() + val recipe = getRecipesFor() + + return recipe?.assemble(enviornment) != null } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index 14e9e2af25..bdf19f0070 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import kotlin.reflect.KClass @@ -13,10 +13,15 @@ object MultiblockRecipeRegistry : IonServerComponent() { - fun > register(recipe: R): R { + fun > register(recipe: R): R { recipes.add(recipe) byMultiblock[recipe.entityType].add(recipe) return recipe } + + fun getRecipesFor(entity: RecipeProcessingMultiblockEntity): Collection> { + @Suppress("UNCHECKED_CAST") + return byMultiblock[entity::class] as Collection> + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt deleted file mode 100644 index 3022f5fe9a..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/BuildableRecipeInput.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.input - -class BuildableRecipeInput { - - - companion object { - fun builder(): Builder = Builder() - } - - class Builder() { - fun build(): BuildableRecipeInput { - return BuildableRecipeInput() - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt deleted file mode 100644 index 777a9789ce..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/DoubleIndustryMultiblockEnviornment.kt +++ /dev/null @@ -1,39 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.input - -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent -import org.bukkit.inventory.FurnaceInventory -import org.bukkit.inventory.ItemStack - -class DoubleIndustryMultiblockEnviornment( - val furnaceInventory: FurnaceInventory, - val powerStorage: PowerStorage, - val tickingManager: TickedMultiblockEntityParent.TickingManager, - val progressManager: ProgressMultiblock.ProgressManager -) : MultiblockRecipeEnviornment { - constructor(entity: MultiblockEntity) : this( - entity.getInventory(0, 0, 0) as FurnaceInventory, - (entity as PoweredMultiblockEntity).powerStorage, - (entity as TickedMultiblockEntityParent).tickingManager, - (entity as ProgressMultiblock).progressManager - ) - - fun getProcessedItem(): ItemStack? = furnaceInventory.smelting - fun getProgress(): Double = progressManager.getCurrentProgress() - - override fun getItemSize(): Int = 2 - override fun getItem(index: Int): ItemStack? { - return when (index) { - 1 -> furnaceInventory.smelting - 2 -> furnaceInventory.fuel - else -> throw IndexOutOfBoundsException() - } - } - - override fun isEmpty(): Boolean { - return furnaceInventory.smelting == null && furnaceInventory.fuel == null - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt similarity index 94% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt index 6ff8b91e6c..3f425821df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/IndustryMultiblockEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt @@ -8,12 +8,12 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedM import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack -class IndustryMultiblockEnviornment( +class FurnaceEnviornment( val furnaceInventory: FurnaceInventory, val powerStorage: PowerStorage, val tickingManager: TickedMultiblockEntityParent.TickingManager, val progressManager: ProgressMultiblock.ProgressManager -) : MultiblockRecipeEnviornment { +) : RecipeEnviornment { constructor(entity: MultiblockEntity) : this( entity.getInventory(0, 0, 0) as FurnaceInventory, (entity as PoweredMultiblockEntity).powerStorage, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt similarity index 83% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt index 6a8835ed96..bd5f26dd19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/MultiblockRecipeEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.input import org.bukkit.inventory.ItemStack -interface MultiblockRecipeEnviornment { +interface RecipeEnviornment { fun getItemSize(): Int fun getItem(index: Int): ItemStack? diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt similarity index 76% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index c466b21b99..3970c8740e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/IndustryMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.IndustryMultiblockEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder @@ -14,21 +14,22 @@ import kotlin.reflect.KClass * @param smeltingItem Requirement for the item in the top slot. If it is null, there will be a requirement for this slot to be empty. * @param fuelitem Requirement for the item in the bottom slot. If it is null, there will be a requirement for this slot to be empty. **/ -class IndustryMultiblockRecipe( - clazz: KClass>, +class FurnaceMultiblockRecipe( + identifier: String, + clazz: KClass>, smeltingItem: ItemRequirement?, fuelitem: ItemRequirement?, power: PowerRequirement, - val result: RecipeResult -) : NewMultiblockRecipe(clazz) { + val result: RecipeResult +) : NewMultiblockRecipe(identifier, clazz) { - override val requirements: Collection> = listOf( + override val requirements: Collection> = listOf( RequirementHolder.of({ it.getItem(0) }, smeltingItem ?: ItemRequirement.empty()), RequirementHolder.of({ it.getItem(1) }, fuelitem ?: ItemRequirement.empty()), RequirementHolder.of({ it.powerStorage.getPower() }, power) ) - override fun assemble(enviornment: IndustryMultiblockEnviornment) { + override fun assemble(enviornment: FurnaceEnviornment) { if (!verifyAllRequirements(enviornment)) result if (result.verifySpace(enviornment)) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt index 6cd5aff8b2..99016bd562 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt @@ -1,12 +1,12 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass -abstract class NewMultiblockRecipe(val entityType: KClass>) { +abstract class NewMultiblockRecipe(val identifier: String, val entityType: KClass>) { protected abstract val requirements: Collection> fun getItemRequirements(): Collection> = requirements @@ -17,7 +17,5 @@ abstract class NewMultiblockRecipe(val entityTyp fun getAllRequirements(): Collection> = requirements - fun ensureRequirementsAvailable(input: E): Boolean - abstract fun assemble(input: E) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt index de20932ca5..e23ae63dec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt @@ -1,15 +1,15 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -class RequirementHolder(val dataTypeClass: Class, val getter: (T) -> V, val requirement: RecipeRequirement) { +class RequirementHolder(val dataTypeClass: Class, val getter: (T) -> V, val requirement: RecipeRequirement) { fun checkRequirement(enviornment: T): Boolean { val resourceValue = getter.invoke(enviornment) return requirement.ensureAvailable(resourceValue) } companion object { - inline fun of( + inline fun of( noinline getter: (T) -> V, requirement: RecipeRequirement ): RequirementHolder = RequirementHolder(V::class.java, getter, requirement) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt new file mode 100644 index 0000000000..64596e4e92 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt @@ -0,0 +1,29 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import org.bukkit.inventory.ItemStack +import java.time.Duration + +class ProgressResult(val duration: Duration, val resultItem: ItemStack) : RecipeResult { + override fun verifySpace(input: FurnaceEnviornment): Boolean { + val resultOccupant = input.furnaceInventory.result ?: return true + if (resultOccupant.isEmpty) return true + if (!resultOccupant.isSimilar(resultItem)) return false + + val maxStackSize = resultItem.maxStackSize + return resultItem.amount + resultItem.amount <= maxStackSize + } + + override fun execute(input: FurnaceEnviornment) { + val complete = input.progressManager.addProgress(duration) + if (!complete) return + + val current = input.furnaceInventory.result + if (current == null) { + input.furnaceInventory.result = resultItem + return + } + + current.amount += resultItem.amount + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt index d1fd086bb2..d6adb43cb9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.MultiblockRecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -interface RecipeResult { +interface RecipeResult { fun verifySpace(input: E): Boolean fun execute(input: E) } From d08a32b00a3b1d094dc72e10a6a454e35ff6e56b Mon Sep 17 00:00:00 2001 From: Gutin1 Date: Thu, 16 Jan 2025 14:09:31 -0600 Subject: [PATCH 400/500] abstract for the future --- .../display/modular/display/DisplayModule.kt | 1 - .../entity/type/ProgressMultiblock.kt | 10 +++++ .../type/RecipeProcessingMultiblockEntity.kt | 2 +- .../newcrafting/MultiblockRecipeRegistry.kt | 15 ++++++- .../newcrafting/input/FurnaceEnviornment.kt | 19 +++++--- .../input/ItemResultEnviornment.kt | 9 ++++ .../recipe/FurnaceMultiblockRecipe.kt | 39 +++++++++++----- .../newcrafting/recipe/NewMultiblockRecipe.kt | 19 +++++--- .../recipe/requirement/Consumable.kt | 10 +++++ .../recipe/requirement/PowerRequirement.kt | 8 +++- .../recipe/requirement/RequirementHolder.kt | 34 ++++++++++++-- .../newcrafting/recipe/result/ItemResult.kt | 44 +++++++++++++++++++ .../recipe/result/ProgressResult.kt | 22 +++++----- .../newcrafting/recipe/result/RecipeResult.kt | 1 - .../newcrafting/recipe/result/ResultHolder.kt | 20 +++++++++ .../util/SlotModificationWrapper.kt | 41 +++++++++++++++++ .../type/industry/CentrifugeMultiblock.kt | 23 +++++++++- 17 files changed, 274 insertions(+), 43 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt index 81616e63d5..589997526f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/DisplayModule.kt @@ -54,7 +54,6 @@ abstract class DisplayModule( ) val location = getLocation() -// println("Location: $location") return craftEntity.getNMSData(location.x, location.y, location.z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 479117c1f0..69b5f74741 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -47,6 +47,16 @@ interface ProgressMultiblock { return currentProgress > 1.0 } + fun wouldComplete(totalDuration: Duration): Boolean { + val now = System.currentTimeMillis() + val deltaMillis = now - lastProgressTick + val delta = Duration.ofMillis(deltaMillis) + + val additionalPercent = totalDuration.toMillis().toDouble() / delta.toMillis().toDouble() + + return currentProgress + additionalPercent >= totalDuration.toMillis() + } + fun reset() { currentProgress = 0.0 } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt index 8b9dca6336..309fa402c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt @@ -10,9 +10,9 @@ interface RecipeProcessingMultiblockEntity { fun getRecipesFor(): NewMultiblockRecipe? { val enviornment = buildRecipeEnviornment() - val recipes = MultiblockRecipeRegistry.getRecipesFor(this) val match = recipes.filter { recipe -> recipe.verifyAllRequirements(enviornment) } + if (match.size > 1) IonServer.slF4JLogger.warn("Multiple recipes match input! This should not happen!!! Infringing recipes: ${match.joinToString { it.identifier }}") return match.firstOrNull() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index bdf19f0070..4304c72087 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -1,9 +1,15 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.FurnaceMultiblockRecipe import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import kotlin.reflect.KClass @@ -11,7 +17,14 @@ object MultiblockRecipeRegistry : IonServerComponent() { val recipes = mutableListOf>() val byMultiblock = multimapOf>, NewMultiblockRecipe<*>>() - + val URANIUM_ENRICHMENT = register(FurnaceMultiblockRecipe( + identifier = "URANIUM_ENRICHMENT", + clazz = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM), + fuelItem = null, + power = PowerRequirement(100), + result = ItemResult.simpleResult(CustomItemRegistry.ENRICHED_URANIUM) + )) fun > register(recipe: R): R { recipes.add(recipe) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt index 3f425821df..4348f2685c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultib import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack @@ -13,7 +14,7 @@ class FurnaceEnviornment( val powerStorage: PowerStorage, val tickingManager: TickedMultiblockEntityParent.TickingManager, val progressManager: ProgressMultiblock.ProgressManager -) : RecipeEnviornment { +) : ItemResultEnviornment { constructor(entity: MultiblockEntity) : this( entity.getInventory(0, 0, 0) as FurnaceInventory, (entity as PoweredMultiblockEntity).powerStorage, @@ -21,14 +22,22 @@ class FurnaceEnviornment( (entity as ProgressMultiblock).progressManager ) - fun getProgress(): Double = progressManager.getCurrentProgress() + val items get() = listOf(furnaceInventory.smelting, furnaceInventory.fuel) - override fun getItemSize(): Int = 1 + override fun getItemSize(): Int = 2 override fun getItem(index: Int): ItemStack? { - return furnaceInventory.smelting + return items[index] } override fun isEmpty(): Boolean { - return furnaceInventory.smelting != null + return items.all { stack -> stack == null || stack.isEmpty } + } + + override fun getResultItem(): ItemStack? { + return furnaceInventory.result + } + + override fun getResultItemSlotModifier(): SlotModificationWrapper { + return SlotModificationWrapper.furnaceResult(furnaceInventory) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt new file mode 100644 index 0000000000..78df2e9471 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.input + +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import org.bukkit.inventory.ItemStack + +interface ItemResultEnviornment : RecipeEnviornment { + fun getResultItem(): ItemStack? + fun getResultItemSlotModifier(): SlotModificationWrapper +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index 3970c8740e..a85b118cae 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -5,33 +5,52 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceE import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.RecipeResult +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import kotlin.reflect.KClass /** * A multiblock recipe that uses a furnace inventory. * * @param smeltingItem Requirement for the item in the top slot. If it is null, there will be a requirement for this slot to be empty. - * @param fuelitem Requirement for the item in the bottom slot. If it is null, there will be a requirement for this slot to be empty. + * @param fuelItem Requirement for the item in the bottom slot. If it is null, there will be a requirement for this slot to be empty. **/ class FurnaceMultiblockRecipe( identifier: String, - clazz: KClass>, + clazz: KClass>, smeltingItem: ItemRequirement?, - fuelitem: ItemRequirement?, + fuelItem: ItemRequirement?, power: PowerRequirement, - val result: RecipeResult + result: ItemResult ) : NewMultiblockRecipe(identifier, clazz) { + private val result = ResultHolder.of(result) - override val requirements: Collection> = listOf( - RequirementHolder.of({ it.getItem(0) }, smeltingItem ?: ItemRequirement.empty()), - RequirementHolder.of({ it.getItem(1) }, fuelitem ?: ItemRequirement.empty()), - RequirementHolder.of({ it.powerStorage.getPower() }, power) + override val requirements: Collection> = listOf( + // Furnace smelting item + RequirementHolder.itemConsumable( + getter = { it.getItem(0) }, + requirement = smeltingItem ?: ItemRequirement.empty(), + { SlotModificationWrapper.furnaceSmelting(it.furnaceInventory) } + ), + // Furnace fuel item + RequirementHolder.itemConsumable( + getter = { it.getItem(1) }, + requirement = fuelItem ?: ItemRequirement.empty(), + { SlotModificationWrapper.furnaceFuel(it.furnaceInventory) } + ), + // Power requirement + RequirementHolder.simpleConsumable( + { it.powerStorage.getPower() }, + power + ) ) override fun assemble(enviornment: FurnaceEnviornment) { if (!verifyAllRequirements(enviornment)) result - if (result.verifySpace(enviornment)) return + if (!result.verifySpace(enviornment)) return + + getAllRequirements().forEach { requirement -> requirement.consume(enviornment) } result.execute(enviornment) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt index 99016bd562..92f7099b62 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt @@ -2,20 +2,27 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.Consumable import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass -abstract class NewMultiblockRecipe(val identifier: String, val entityType: KClass>) { - protected abstract val requirements: Collection> +abstract class NewMultiblockRecipe(val identifier: String, val entityType: KClass>) { + protected abstract val requirements: Collection> - fun getItemRequirements(): Collection> = requirements + fun getConsumableRequirements(): Collection>> = requirements + .filter { holder -> holder.requirement is Consumable<* , *> } + .filterIsInstance>>() + + fun getItemRequirements(): Collection> = requirements .filter { it.dataTypeClass == ItemStack::class.java } - .filterIsInstance>() + .filterIsInstance>() - fun verifyAllRequirements(enviornment: E): Boolean = getAllRequirements().all { holder -> holder.checkRequirement(enviornment) } + fun verifyAllRequirements(enviornment: E): Boolean = getAllRequirements().all { holder -> + holder.checkRequirement(enviornment) + } - fun getAllRequirements(): Collection> = requirements + fun getAllRequirements(): Collection> = requirements abstract fun assemble(input: E) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt new file mode 100644 index 0000000000..3a898f4007 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt @@ -0,0 +1,10 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment + +/** + * Represents a resource that is easily consumable from the enviornment, such as power + **/ +interface Consumable : RecipeRequirement { + fun consume(enviornment: E) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt index 685aa60e93..2995213cea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt @@ -1,7 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement -class PowerRequirement(val amount: Int) : RecipeRequirement { +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment + +class PowerRequirement(val amount: Int) : Consumable { override fun ensureAvailable(resource: Int): Boolean { return resource >= amount } + + override fun consume(enviornment: FurnaceEnviornment) { + enviornment.powerStorage.removePower(amount) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt index e23ae63dec..67f5a9780b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt @@ -1,17 +1,43 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper -class RequirementHolder(val dataTypeClass: Class, val getter: (T) -> V, val requirement: RecipeRequirement) { +open class RequirementHolder>(val dataTypeClass: Class, val getter: (T) -> V, val requirement: R) { fun checkRequirement(enviornment: T): Boolean { val resourceValue = getter.invoke(enviornment) return requirement.ensureAvailable(resourceValue) } + open fun consume(enviornment: T) { + if (requirement is Consumable<*, *>) { + @Suppress("UNCHECKED_CAST") + (requirement as Consumable).consume(enviornment) + } + } + + class BundledRequirementHolder>( + dataTypeClass: Class, + getter: (T) -> V, + requirement: R, + val slotModificationWrapper: (T) -> SlotModificationWrapper + ) : RequirementHolder(dataTypeClass, getter, requirement) { + override fun consume(enviornment: T) { + val wrapper = slotModificationWrapper.invoke(enviornment) + wrapper.removeFromSlot(1) + } + } + companion object { - inline fun of( + inline fun > simpleConsumable( + noinline getter: (T) -> V, + requirement: R, + ): RequirementHolder = RequirementHolder(V::class.java, getter, requirement) + + inline fun > itemConsumable( noinline getter: (T) -> V, - requirement: RecipeRequirement - ): RequirementHolder = RequirementHolder(V::class.java, getter, requirement) + requirement: R, + noinline slotModificationWrapper: (T) -> SlotModificationWrapper, + ): RequirementHolder = BundledRequirementHolder(V::class.java, getter, requirement, slotModificationWrapper) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt new file mode 100644 index 0000000000..c05e6a0458 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt @@ -0,0 +1,44 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.horizonsend.ion.server.features.custom.items.CustomItem +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import org.bukkit.Material +import org.bukkit.inventory.ItemStack + +interface ItemResult : RecipeResult { + override fun verifySpace(enviornment: E): Boolean { + val resultOccupant = enviornment.getResultItem() ?: return true + if (resultOccupant.isEmpty) return true + + val resultItem = getResultItem(enviornment) ?: return true + + if (!resultOccupant.isSimilar(resultItem)) return false + + val maxStackSize = resultItem.maxStackSize + return resultOccupant.amount + resultItem.amount <= maxStackSize + } + + /** + * Executes the result + **/ + fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) + + /** + * Gets the result item. + **/ + fun getResultItem(enviornment: E): ItemStack? + + companion object { + fun simpleResult(itemStack: ItemStack): SimpleResult = SimpleResult(itemStack) + fun simpleResult(customItem: CustomItem): SimpleResult = SimpleResult(customItem.constructItemStack()) + fun simpleResult(material: Material): SimpleResult = SimpleResult(ItemStack(material, 1)) + } + + class SimpleResult(private val item: ItemStack) : ItemResult { + override fun getResultItem(enviornment: E): ItemStack? = item + override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) { + slotModificationWrapper.addToSlot(item) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt index 64596e4e92..8594d742b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt @@ -1,12 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import org.bukkit.inventory.ItemStack import java.time.Duration -class ProgressResult(val duration: Duration, val resultItem: ItemStack) : RecipeResult { - override fun verifySpace(input: FurnaceEnviornment): Boolean { - val resultOccupant = input.furnaceInventory.result ?: return true +class ProgressResult(val duration: Duration, val resultItem: ItemStack) : ItemResult { + override fun verifySpace(enviornment: FurnaceEnviornment): Boolean { + val resultOccupant = enviornment.furnaceInventory.result ?: return true if (resultOccupant.isEmpty) return true if (!resultOccupant.isSimilar(resultItem)) return false @@ -14,16 +15,15 @@ class ProgressResult(val duration: Duration, val resultItem: ItemStack) : Recipe return resultItem.amount + resultItem.amount <= maxStackSize } - override fun execute(input: FurnaceEnviornment) { - val complete = input.progressManager.addProgress(duration) + override fun execute(enviornment: FurnaceEnviornment, slotModificationWrapper: SlotModificationWrapper) { + val complete = enviornment.progressManager.addProgress(duration) if (!complete) return - val current = input.furnaceInventory.result - if (current == null) { - input.furnaceInventory.result = resultItem - return - } + slotModificationWrapper.addToSlot(resultItem) + } - current.amount += resultItem.amount + override fun getResultItem(enviornment: FurnaceEnviornment): ItemStack? { + if (!enviornment.progressManager.wouldComplete(duration)) return null + return resultItem } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt index d6adb43cb9..1bed3e1b19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -4,5 +4,4 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEn interface RecipeResult { fun verifySpace(input: E): Boolean - fun execute(input: E) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt new file mode 100644 index 0000000000..5924ed968e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment + +abstract class ResultHolder>(val result: R) { + fun verifySpace(input: E) = result.verifySpace(input) + abstract fun execute(input: E) + + class ItemResultHolder>(result: R) : ResultHolder(result) { + override fun execute(enviornment: E) { + val slotModificationWrapper = enviornment.getResultItemSlotModifier() + result.execute(enviornment, slotModificationWrapper) + } + } + + companion object { + fun of(result: ItemResult) = ItemResultHolder(result) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt new file mode 100644 index 0000000000..7ae405f30a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt @@ -0,0 +1,41 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.util + +import com.google.common.base.Supplier +import org.bukkit.inventory.FurnaceInventory +import org.bukkit.inventory.ItemStack +import java.util.function.Consumer + +/** + * Handles the addition of items to a slot in an inventory + **/ +class SlotModificationWrapper(private val getter: Supplier, private val setter: Consumer) { + fun removeFromSlot(amount: Int) { + getter.get()?.amount -= amount + } + + fun addToSlot(newItem: ItemStack) { + val currentItem = getter.get() + + if (currentItem == null || currentItem.isEmpty) { + setter.accept(newItem) + return + } + + currentItem.amount = (currentItem.amount + newItem.amount).coerceIn(1, newItem.maxStackSize) + } + + fun verifySpace(newItem: ItemStack): Boolean { + val resultOccupant = getter.get() ?: return true + if (resultOccupant.isEmpty) return true + if (!resultOccupant.isSimilar(newItem)) return false + + val maxStackSize = resultOccupant.maxStackSize + return resultOccupant.amount + newItem.amount <= maxStackSize + } + + companion object { + fun furnaceSmelting(inventory: FurnaceInventory): SlotModificationWrapper = SlotModificationWrapper(inventory::getSmelting, inventory::setSmelting) + fun furnaceFuel(inventory: FurnaceInventory): SlotModificationWrapper = SlotModificationWrapper(inventory::getFuel, inventory::setFuel) + fun furnaceResult(inventory: FurnaceInventory): SlotModificationWrapper = SlotModificationWrapper(inventory::getResult, inventory::setResult) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index f4f4ab1ba1..d30de84d6d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -3,9 +3,13 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.World @@ -118,13 +122,28 @@ object CentrifugeMultiblock : Multiblock(), EntityMultiblock, + ProgressMultiblock { + override val multiblock: CentrifugeMultiblock = CentrifugeMultiblock + override val progressManager: ProgressMultiblock.ProgressManager = ProgressMultiblock.ProgressManager(data) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) override val displayHandler = standardPowerDisplay(this) override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) } + + override fun buildRecipeEnviornment(): FurnaceEnviornment { + return FurnaceEnviornment(this) + } + + override fun tick() { + tryProcessRecipe() + } } } From 0d73b1b2b7c35499e3d0d2aae3317643fe75c254 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 16 Jan 2025 14:42:28 -0600 Subject: [PATCH 401/500] more code --- .../newcrafting/MultiblockRecipeRegistry.kt | 8 +++++++- .../newcrafting/input/FurnaceEnviornment.kt | 8 ++++++++ .../newcrafting/input/RecipeEnviornment.kt | 3 +++ .../newcrafting/recipe/FurnaceMultiblockRecipe.kt | 4 ++-- .../recipe/requirement/ItemRequirement.kt | 14 ++++++++++++++ .../newcrafting/recipe/result/ItemResult.kt | 10 ++++++---- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index 4304c72087..032c77b69b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -10,7 +10,10 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.require import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.multimapOf +import net.kyori.adventure.sound.Sound +import org.bukkit.SoundCategory import kotlin.reflect.KClass object MultiblockRecipeRegistry : IonServerComponent() { @@ -23,7 +26,10 @@ object MultiblockRecipeRegistry : IonServerComponent() { smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM), fuelItem = null, power = PowerRequirement(100), - result = ItemResult.simpleResult(CustomItemRegistry.ENRICHED_URANIUM) + result = ItemResult.simpleResult( + CustomItemRegistry.ENRICHED_URANIUM, + Sound.sound(NamespacedKeys.packKey("industry.centrifuge"), SoundCategory.BLOCKS, 1.0f, 1.0f) + ) )) fun > register(recipe: R): R { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt index 4348f2685c..bf39fdf05e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerSto import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.kyori.adventure.sound.Sound import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack @@ -40,4 +41,11 @@ class FurnaceEnviornment( override fun getResultItemSlotModifier(): SlotModificationWrapper { return SlotModificationWrapper.furnaceResult(furnaceInventory) } + + override fun playSound(sound: Sound) { + val furnaceLocation = furnaceInventory.holder?.location?.toCenterLocation() + ?: throw IllegalStateException("Virtual furnace inventory passed to multiblock recipe! Don't do that!") + + furnaceLocation.world.playSound(sound, furnaceLocation.x, furnaceLocation.y, furnaceLocation.z) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt index bd5f26dd19..aeb0b9ff36 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.input +import net.kyori.adventure.sound.Sound import org.bukkit.inventory.ItemStack interface RecipeEnviornment { @@ -7,4 +8,6 @@ interface RecipeEnviornment { fun getItem(index: Int): ItemStack? fun isEmpty(): Boolean + + fun playSound(sound: Sound) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index a85b118cae..a6dbe57aba 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -30,13 +30,13 @@ class FurnaceMultiblockRecipe( // Furnace smelting item RequirementHolder.itemConsumable( getter = { it.getItem(0) }, - requirement = smeltingItem ?: ItemRequirement.empty(), + requirement = smeltingItem ?: ItemRequirement.legacy(), { SlotModificationWrapper.furnaceSmelting(it.furnaceInventory) } ), // Furnace fuel item RequirementHolder.itemConsumable( getter = { it.getItem(1) }, - requirement = fuelItem ?: ItemRequirement.empty(), + requirement = fuelItem ?: ItemRequirement.legacy(), { SlotModificationWrapper.furnaceFuel(it.furnaceInventory) } ), // Power requirement diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt index 335fef17f4..e8a5d5c9b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt @@ -40,5 +40,19 @@ fun interface ItemRequirement : RecipeRequirement { if (it == null) return@ItemRequirement true it.isEmpty } + + /** Gets an item requirement is always true */ + fun ignore() = ItemRequirement { true } + + fun prismarine() = MaterialRequirement(Material.PRISMARINE_CRYSTALS) + + /** Gets a composite requirement where it could be prismarine crystals or empty */ + fun legacy() = any(prismarine(), empty()) + + /** Gets a composite requirement where any condition could be met */ + fun any(vararg requirements: ItemRequirement) = ItemRequirement { requirements.any { requirement -> requirement.matches(it) } } + + /** Gets a composite requirement where all conditions must be met */ + fun all(vararg requirements: ItemRequirement) = ItemRequirement { requirements.all { requirement -> requirement.matches(it) } } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt index c05e6a0458..0b604c4a4f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.kyori.adventure.sound.Sound import org.bukkit.Material import org.bukkit.inventory.ItemStack @@ -30,15 +31,16 @@ interface ItemResult : RecipeResult { fun getResultItem(enviornment: E): ItemStack? companion object { - fun simpleResult(itemStack: ItemStack): SimpleResult = SimpleResult(itemStack) - fun simpleResult(customItem: CustomItem): SimpleResult = SimpleResult(customItem.constructItemStack()) - fun simpleResult(material: Material): SimpleResult = SimpleResult(ItemStack(material, 1)) + fun simpleResult(itemStack: ItemStack,sound: Sound? = null): SimpleResult = SimpleResult(itemStack, sound) + fun simpleResult(customItem: CustomItem,sound: Sound? = null): SimpleResult = SimpleResult(customItem.constructItemStack(), sound) + fun simpleResult(material: Material,sound: Sound? = null): SimpleResult = SimpleResult(ItemStack(material, 1), sound) } - class SimpleResult(private val item: ItemStack) : ItemResult { + class SimpleResult(private val item: ItemStack, val sound: Sound? = null) : ItemResult { override fun getResultItem(enviornment: E): ItemStack? = item override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) { slotModificationWrapper.addToSlot(item) + sound?.let { enviornment.playSound(it) } } } } From 087835cbd0a7eaee0e859a6e4abf25023e4f1f53 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:31:49 -0600 Subject: [PATCH 402/500] Add progress recipe for testing --- .../newcrafting/MultiblockRecipeRegistry.kt | 15 ++++++++++++++ .../type/industry/CentrifugeMultiblock.kt | 1 - .../type/industry/CompressorMultiblock.kt | 20 ++++++++++++++++--- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index 032c77b69b..4204a49609 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting +import io.papermc.paper.util.Tick import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity @@ -9,7 +10,9 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMult import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ProgressResult import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import net.kyori.adventure.sound.Sound @@ -32,6 +35,18 @@ object MultiblockRecipeRegistry : IonServerComponent() { ) )) + val URANIUM_CORE_COMPRESSION = register(FurnaceMultiblockRecipe( + identifier = "URANIUM_CORE_COMPRESSION", + clazz = CompressorMultiblock.CompressorMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM_CORE), + fuelItem = null, + power = PowerRequirement(100), + result = ProgressResult( + Tick.of(60L * 60L * 20L), + CustomItemRegistry.ENRICHED_URANIUM.constructItemStack() + ) + )) + fun > register(recipe: R): R { recipes.add(recipe) byMultiblock[recipe.entityType].add(recipe) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index d30de84d6d..ea36083ecf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -128,7 +128,6 @@ object CentrifugeMultiblock : Multiblock(), EntityMultiblock, ProgressMultiblock { - override val multiblock: CentrifugeMultiblock = CentrifugeMultiblock override val progressManager: ProgressMultiblock.ProgressManager = ProgressMultiblock.ProgressManager(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt index 238313fed1..9ef1c311ee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt @@ -4,11 +4,12 @@ import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.World @@ -125,7 +126,12 @@ object CompressorMultiblock : Multiblock(), EntityMultiblock, + ProgressMultiblock { + override val displayHandler = standardPowerDisplay(this) override val progressManager: ProgressMultiblock.ProgressManager = ProgressMultiblock.ProgressManager(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) @@ -133,5 +139,13 @@ object CompressorMultiblock : Multiblock(), EntityMultiblock Date: Thu, 16 Jan 2025 17:52:38 -0600 Subject: [PATCH 403/500] some optimizations, work on progress recipes, fix tick interval --- .../ion/common/utils/miscellaneous/Numbers.kt | 1 + .../entity/type/ProgressMultiblock.kt | 27 +++++++-------- .../type/RecipeProcessingMultiblockEntity.kt | 11 ++++++- .../ticked/TickedMultiblockEntityParent.kt | 6 ++-- .../newcrafting/MultiblockRecipeRegistry.kt | 4 +-- .../newcrafting/input/FurnaceEnviornment.kt | 2 ++ .../input/ItemResultEnviornment.kt | 2 ++ .../recipe/FurnaceMultiblockRecipe.kt | 13 +++++++- .../newcrafting/recipe/result/ItemResult.kt | 1 + .../recipe/result/ProgressResult.kt | 13 ++++++++ .../newcrafting/recipe/result/RecipeResult.kt | 4 ++- .../newcrafting/recipe/result/ResultHolder.kt | 3 +- .../type/industry/CentrifugeMultiblock.kt | 3 +- .../type/industry/CompressorMultiblock.kt | 33 +++++++++++++++---- 14 files changed, 95 insertions(+), 28 deletions(-) diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/miscellaneous/Numbers.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/miscellaneous/Numbers.kt index 66589046ec..bd1a6fac7d 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/miscellaneous/Numbers.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/miscellaneous/Numbers.kt @@ -9,6 +9,7 @@ import kotlin.random.Random import kotlin.random.asKotlinRandom fun Double.roundToHundredth(): Double = times(100.0).roundToInt().toDouble().div(100.0) +fun Double.roundToTenThousanth(): Double = times(10000.0).roundToInt().toDouble().div(10000.0) @Suppress("NOTHING_TO_INLINE") inline fun Int.squared(): Int = this * this diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 69b5f74741..7bfc58d819 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.multiblock.entity.type -import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth +import net.horizonsend.ion.common.utils.miscellaneous.roundToTenThousanth import net.horizonsend.ion.common.utils.text.colors.HEColorScheme import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData @@ -11,6 +11,7 @@ import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.TextColor import org.bukkit.persistence.PersistentDataType.DOUBLE import org.bukkit.persistence.PersistentDataType.LONG +import java.text.DecimalFormat import java.time.Duration interface ProgressMultiblock { @@ -20,7 +21,7 @@ interface ProgressMultiblock { } class ProgressManager(data: PersistentMultiblockData) { - var lastProgressTick: Long = data.getAdditionalDataOrDefault(LAST_PROGRESS_TICK, LONG, System.currentTimeMillis()) + var lastProgressTick = System.currentTimeMillis() private var currentProgress: Double = data.getAdditionalDataOrDefault(PROGRESS, DOUBLE, 0.0) fun getCurrentProgress(): Double = currentProgress @@ -31,30 +32,29 @@ interface ProgressMultiblock { **/ fun addProgress(totalDuration: Duration): Boolean { val now = System.currentTimeMillis() - val deltaMillis = now - lastProgressTick - val delta = Duration.ofMillis(deltaMillis) - + val additionalPercent = calculatePercentageGain(now, totalDuration) lastProgressTick = now - // Convert the delta to a percentage of the total duration, and add that percentage - val additionalPercent = totalDuration.toMillis().toDouble() / delta.toMillis().toDouble() currentProgress += additionalPercent return isComplete() } + fun wouldComplete(totalDuration: Duration): Boolean { + val additionalPercent = calculatePercentageGain(System.currentTimeMillis(), totalDuration) + + return (currentProgress + additionalPercent) >= totalDuration.toMillis() + } + fun isComplete(): Boolean { return currentProgress > 1.0 } - fun wouldComplete(totalDuration: Duration): Boolean { - val now = System.currentTimeMillis() + fun calculatePercentageGain(now: Long, totalDuration: Duration): Double { val deltaMillis = now - lastProgressTick val delta = Duration.ofMillis(deltaMillis) - val additionalPercent = totalDuration.toMillis().toDouble() / delta.toMillis().toDouble() - - return currentProgress + additionalPercent >= totalDuration.toMillis() + return delta.toMillis().toDouble() / totalDuration.toMillis().toDouble() } fun reset() { @@ -67,7 +67,8 @@ interface ProgressMultiblock { } fun formatProgress(color: TextColor): Component { - return ofChildren(text(currentProgress.roundToHundredth() * 100.0, color), text('%', HEColorScheme.HE_LIGHT_GRAY)) + val percent = DecimalFormat("##.##").format(getCurrentProgress().roundToTenThousanth() * 100.0) + return ofChildren(text(percent, color), text('%', HEColorScheme.HE_LIGHT_GRAY)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt index 309fa402c3..c127141a43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt @@ -6,10 +6,15 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEn import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe interface RecipeProcessingMultiblockEntity { + var lastRecipe: NewMultiblockRecipe? + fun buildRecipeEnviornment(): E fun getRecipesFor(): NewMultiblockRecipe? { val enviornment = buildRecipeEnviornment() + // Optimization step, avoid checking all recipes + if (lastRecipe?.verifyAllRequirements(enviornment) == true) return lastRecipe + val recipes = MultiblockRecipeRegistry.getRecipesFor(this) val match = recipes.filter { recipe -> recipe.verifyAllRequirements(enviornment) } @@ -19,9 +24,13 @@ interface RecipeProcessingMultiblockEntity { } fun tryProcessRecipe(): Boolean { - val enviornment = buildRecipeEnviornment() val recipe = getRecipesFor() + if (this is ProgressMultiblock && (recipe == null || lastRecipe != recipe)) progressManager.reset() + + lastRecipe = recipe + + val enviornment = buildRecipeEnviornment() return recipe?.assemble(enviornment) != null } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt index badfc3cf0f..7d5bd31ddf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt @@ -23,11 +23,13 @@ interface TickedMultiblockEntityParent { } currentTick++ - if (currentTick >= interval) { - currentTick = 0 + + if (currentTick <= interval) { return false } + currentTick = 0 + return true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index 4204a49609..634da1c491 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -43,11 +43,11 @@ object MultiblockRecipeRegistry : IonServerComponent() { power = PowerRequirement(100), result = ProgressResult( Tick.of(60L * 60L * 20L), - CustomItemRegistry.ENRICHED_URANIUM.constructItemStack() + CustomItemRegistry.URANIUM_ROD.constructItemStack() ) )) - fun > register(recipe: R): R { + fun > register(recipe: R): R { recipes.add(recipe) byMultiblock[recipe.entityType].add(recipe) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt index bf39fdf05e..61c4d47ae0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt @@ -11,12 +11,14 @@ import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack class FurnaceEnviornment( + override val multiblock: MultiblockEntity, val furnaceInventory: FurnaceInventory, val powerStorage: PowerStorage, val tickingManager: TickedMultiblockEntityParent.TickingManager, val progressManager: ProgressMultiblock.ProgressManager ) : ItemResultEnviornment { constructor(entity: MultiblockEntity) : this( + entity, entity.getInventory(0, 0, 0) as FurnaceInventory, (entity as PoweredMultiblockEntity).powerStorage, (entity as TickedMultiblockEntityParent).tickingManager, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt index 78df2e9471..0351683536 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt @@ -1,9 +1,11 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.input +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import org.bukkit.inventory.ItemStack interface ItemResultEnviornment : RecipeEnviornment { + val multiblock: MultiblockEntity fun getResultItem(): ItemStack? fun getResultItemSlotModifier(): SlotModificationWrapper } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index a6dbe57aba..7353f4a719 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.require import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import java.util.function.Consumer import kotlin.reflect.KClass /** @@ -24,6 +25,7 @@ class FurnaceMultiblockRecipe( power: PowerRequirement, result: ItemResult ) : NewMultiblockRecipe(identifier, clazz) { + val callbacks = mutableListOf>() private val result = ResultHolder.of(result) override val requirements: Collection> = listOf( @@ -46,12 +48,21 @@ class FurnaceMultiblockRecipe( ) ) + fun withCallback(consumer: Consumer): FurnaceMultiblockRecipe { + callbacks.add(consumer) + return this + } + override fun assemble(enviornment: FurnaceEnviornment) { if (!verifyAllRequirements(enviornment)) result if (!result.verifySpace(enviornment)) return - getAllRequirements().forEach { requirement -> requirement.consume(enviornment) } + if (result.shouldConsumeIngredients(enviornment)) { + println("Should consume ingredients") + getAllRequirements().forEach { requirement -> requirement.consume(enviornment) } + } result.execute(enviornment) + callbacks.forEach { consumer -> consumer.accept(enviornment) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt index 0b604c4a4f..de3d517a01 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt @@ -38,6 +38,7 @@ interface ItemResult : RecipeResult { class SimpleResult(private val item: ItemStack, val sound: Sound? = null) : ItemResult { override fun getResultItem(enviornment: E): ItemStack? = item + override fun shouldConsumeIngredients(enviornment: E): Boolean = true override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) { slotModificationWrapper.addToSlot(item) sound?.let { enviornment.playSound(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt index 8594d742b4..4d52758c95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt @@ -1,7 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.inventory.ItemStack import java.time.Duration @@ -15,10 +17,21 @@ class ProgressResult(val duration: Duration, val resultItem: ItemStack) : ItemRe return resultItem.amount + resultItem.amount <= maxStackSize } + override fun shouldConsumeIngredients(enviornment: FurnaceEnviornment): Boolean { + return enviornment.progressManager.wouldComplete(duration) + } + override fun execute(enviornment: FurnaceEnviornment, slotModificationWrapper: SlotModificationWrapper) { val complete = enviornment.progressManager.addProgress(duration) + + val multiblock = enviornment.multiblock + if (multiblock is StatusMultiblockEntity) multiblock.setStatus(enviornment.progressManager.formatProgress(NamedTextColor.RED)) + if (!complete) return + if (multiblock is StatusMultiblockEntity) multiblock.setStatus(enviornment.progressManager.formatProgress(NamedTextColor.GREEN)) + + enviornment.progressManager.reset() slotModificationWrapper.addToSlot(resultItem) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt index 1bed3e1b19..a212d8e6f9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -3,5 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment interface RecipeResult { - fun verifySpace(input: E): Boolean + fun shouldConsumeIngredients(enviornment: E): Boolean + + fun verifySpace(enviornment: E): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt index 5924ed968e..6e2151cc30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt @@ -4,7 +4,8 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResu import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment abstract class ResultHolder>(val result: R) { - fun verifySpace(input: E) = result.verifySpace(input) + fun verifySpace(enviornment: E) = result.verifySpace(enviornment) + fun shouldConsumeIngredients(enviornment: E): Boolean = result.shouldConsumeIngredients(enviornment) abstract fun execute(input: E) class ItemResultHolder>(result: R) : ResultHolder(result) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index ea36083ecf..d0208ee899 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -10,6 +10,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.World @@ -127,7 +128,7 @@ object CentrifugeMultiblock : Multiblock(), EntityMultiblock, ProgressMultiblock { - + override var lastRecipe: NewMultiblockRecipe? = null override val progressManager: ProgressMultiblock.ProgressManager = ProgressMultiblock.ProgressManager(data) override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt index 9ef1c311ee..a9973f352d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CompressorMultiblock.kt @@ -1,20 +1,28 @@ package net.horizonsend.ion.server.features.multiblock.type.industry +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock.ProgressManager import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity.StatusManager import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataAdapterContext object CompressorMultiblock : Multiblock(), EntityMultiblock { @@ -125,16 +133,24 @@ object CompressorMultiblock : Multiblock(), EntityMultiblock, - ProgressMultiblock { + ProgressMultiblock, + StatusTickedMultiblockEntity { + override val progressManager: ProgressManager = ProgressManager(data) + override val tickingManager: TickingManager = TickingManager(20) + override val statusManager: StatusManager = StatusManager() - override val displayHandler = standardPowerDisplay(this) - override val progressManager: ProgressMultiblock.ProgressManager = ProgressMultiblock.ProgressManager(data) - override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) + override var lastRecipe: NewMultiblockRecipe? = null + + override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + { PowerEntityDisplayModule(it, this) }, + { StatusDisplayModule(it, statusManager) } + ) override fun loadFromSign(sign: Sign) { migrateLegacyPower(sign) @@ -147,5 +163,10 @@ object CompressorMultiblock : Multiblock(), EntityMultiblock Date: Thu, 16 Jan 2025 18:17:05 -0600 Subject: [PATCH 404/500] Add industry entity, migrate industry entities to it --- .../entity/type/power/IndustryEntity.kt | 60 +++++++++++++++++++ .../ticked/TickedMultiblockEntityParent.kt | 2 +- .../type/ammo/AmmoLoaderMultiblock.kt | 18 +----- .../type/ammo/MissileLoaderMultiblock.kt | 18 +----- .../type/farming/planter/PlanterMultiblock.kt | 4 +- .../type/industry/CentrifugeMultiblock.kt | 34 +---------- .../type/industry/CircuitfabMultiblock.kt | 14 +---- .../type/industry/CompressorMultiblock.kt | 53 +--------------- .../type/industry/FabricatorMultiblock.kt | 18 +----- .../type/industry/GasFurnaceMultiblock.kt | 18 +----- .../type/industry/PlatePressMultiblock.kt | 18 +----- 11 files changed, 79 insertions(+), 178 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt new file mode 100644 index 0000000000..69198a6a88 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt @@ -0,0 +1,60 @@ +package net.horizonsend.ion.server.features.multiblock.entity.type.power + +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock.ProgressManager +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity.StatusManager +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.persistence.PersistentDataAdapterContext + +abstract class IndustryEntity(data: PersistentMultiblockData, multiblock: Multiblock, manager: MultiblockManager, x: Int, y: Int, z: Int, world: World, structureDirection: BlockFace, maxPower: Int) : + SimplePoweredEntity(data, multiblock, manager, x, y, z, world, structureDirection, maxPower), + LegacyMultiblockEntity, + SyncTickingMultiblockEntity, + RecipeProcessingMultiblockEntity, + ProgressMultiblock, + StatusTickedMultiblockEntity { + + override var lastRecipe: NewMultiblockRecipe? = null + + override val progressManager: ProgressManager = ProgressManager(data) + override val tickingManager: TickingManager = TickingManager(20) + override val statusManager: StatusManager = StatusManager() + + final override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + { PowerEntityDisplayModule(it, this) }, + { StatusDisplayModule(it, statusManager) } + ) + + override fun loadFromSign(sign: Sign) { + migrateLegacyPower(sign) + } + + override fun buildRecipeEnviornment(): FurnaceEnviornment { + return FurnaceEnviornment(this) + } + + override fun tick() { + tryProcessRecipe() + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + progressManager.saveProgressData(store) + super.storeAdditionalData(store, adapterContext) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt index 7d5bd31ddf..bd7b0365f6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt @@ -4,7 +4,7 @@ interface TickedMultiblockEntityParent { val tickingManager: TickingManager /** - * + * Whether to check multiblock integrity before ticking **/ fun shouldCheckIntegrity(): Boolean = true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index dcc0ec27c3..93b6304ad4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -2,19 +2,13 @@ package net.horizonsend.ion.server.features.multiblock.type.ammo import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.entity.type.power.IndustryEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Sign object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { @@ -149,13 +143,5 @@ object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { @@ -151,13 +145,5 @@ object MissileLoaderMultiblock : Multiblock(), EntityMultiblock { @@ -123,27 +115,5 @@ object CentrifugeMultiblock : Multiblock(), EntityMultiblock, - ProgressMultiblock { - override var lastRecipe: NewMultiblockRecipe? = null - override val progressManager: ProgressMultiblock.ProgressManager = ProgressMultiblock.ProgressManager(data) - override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(20) - - override val displayHandler = standardPowerDisplay(this) - - override fun loadFromSign(sign: Sign) { - migrateLegacyPower(sign) - } - - override fun buildRecipeEnviornment(): FurnaceEnviornment { - return FurnaceEnviornment(this) - } - - override fun tick() { - tryProcessRecipe() - } - } + ) : IndustryEntity(data, CentrifugeMultiblock, manager, x, y, z, world, structureDirection, 300_000) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt index 2b673ca425..18c8277457 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CircuitfabMultiblock.kt @@ -2,16 +2,13 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.IndustryEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Sign object CircuitfabMultiblock : Multiblock(), EntityMultiblock { override val name = "circuitfab" @@ -86,12 +83,5 @@ object CircuitfabMultiblock : Multiblock(), EntityMultiblock { @@ -134,39 +119,5 @@ object CompressorMultiblock : Multiblock(), EntityMultiblock, - ProgressMultiblock, - StatusTickedMultiblockEntity { - override val progressManager: ProgressManager = ProgressManager(data) - override val tickingManager: TickingManager = TickingManager(20) - override val statusManager: StatusManager = StatusManager() - - override var lastRecipe: NewMultiblockRecipe? = null - - override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( - this, - { PowerEntityDisplayModule(it, this) }, - { StatusDisplayModule(it, statusManager) } - ) - - override fun loadFromSign(sign: Sign) { - migrateLegacyPower(sign) - } - - override fun buildRecipeEnviornment(): FurnaceEnviornment { - return FurnaceEnviornment(this) - } - - override fun tick() { - tryProcessRecipe() - } - - override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { - progressManager.saveProgressData(store) - super.storeAdditionalData(store, adapterContext) - } - } + ) : IndustryEntity(data, CompressorMultiblock, manager, x, y, z, world, structureFace, 300_000) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt index 44f5dbe200..0beaf379ff 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/FabricatorMultiblock.kt @@ -2,19 +2,13 @@ package net.horizonsend.ion.server.features.multiblock.type.industry import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock -import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.entity.type.power.IndustryEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Sign object FabricatorMultiblock : Multiblock(), EntityMultiblock { @@ -116,13 +110,5 @@ object FabricatorMultiblock : Multiblock(), EntityMultiblock { override val name = "gasfurnace" @@ -88,13 +82,5 @@ object GasFurnaceMultiblock : Multiblock(), EntityMultiblock { override fun MultiblockShape.buildStructure() { @@ -125,13 +119,5 @@ object PlatePressMultiblock : Multiblock(), EntityMultiblock Date: Thu, 16 Jan 2025 18:32:57 -0600 Subject: [PATCH 405/500] fix progress result power consumption during normal ticking --- .../newcrafting/recipe/FurnaceMultiblockRecipe.kt | 7 +++---- .../multiblock/newcrafting/recipe/result/ItemResult.kt | 3 ++- .../newcrafting/recipe/result/ProgressResult.kt | 10 ++++++++-- .../newcrafting/recipe/result/RecipeResult.kt | 3 ++- .../newcrafting/recipe/result/ResultHolder.kt | 3 ++- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index 7353f4a719..d46a37e5f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -57,10 +57,9 @@ class FurnaceMultiblockRecipe( if (!verifyAllRequirements(enviornment)) result if (!result.verifySpace(enviornment)) return - if (result.shouldConsumeIngredients(enviornment)) { - println("Should consume ingredients") - getAllRequirements().forEach { requirement -> requirement.consume(enviornment) } - } + result + .filterConsumedIngredients(enviornment, getAllRequirements()) + .forEach { requirement -> requirement.consume(enviornment) } result.execute(enviornment) callbacks.forEach { consumer -> consumer.accept(enviornment) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt index de3d517a01..2d7a910d95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import net.kyori.adventure.sound.Sound import org.bukkit.Material @@ -38,7 +39,7 @@ interface ItemResult : RecipeResult { class SimpleResult(private val item: ItemStack, val sound: Sound? = null) : ItemResult { override fun getResultItem(enviornment: E): ItemStack? = item - override fun shouldConsumeIngredients(enviornment: E): Boolean = true + override fun filterConsumedIngredients(enviornment: E, ingreidents: Collection>): Collection> = ingreidents override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) { slotModificationWrapper.addToSlot(item) sound?.let { enviornment.playSound(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt index 4d52758c95..19ea0c5034 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.inventory.ItemStack @@ -17,8 +19,12 @@ class ProgressResult(val duration: Duration, val resultItem: ItemStack) : ItemRe return resultItem.amount + resultItem.amount <= maxStackSize } - override fun shouldConsumeIngredients(enviornment: FurnaceEnviornment): Boolean { - return enviornment.progressManager.wouldComplete(duration) + override fun filterConsumedIngredients( + enviornment: FurnaceEnviornment, + ingreidents: Collection> + ): Collection> { + if (enviornment.progressManager.wouldComplete(duration)) return ingreidents + return ingreidents.filterNot { holder -> holder.requirement is ItemRequirement } } override fun execute(enviornment: FurnaceEnviornment, slotModificationWrapper: SlotModificationWrapper) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt index a212d8e6f9..60e7902458 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -1,9 +1,10 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder interface RecipeResult { - fun shouldConsumeIngredients(enviornment: E): Boolean + fun filterConsumedIngredients(enviornment: E, ingreidents: Collection>): Collection> fun verifySpace(enviornment: E): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt index 6e2151cc30..0911ef57d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt @@ -2,10 +2,11 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder abstract class ResultHolder>(val result: R) { fun verifySpace(enviornment: E) = result.verifySpace(enviornment) - fun shouldConsumeIngredients(enviornment: E): Boolean = result.shouldConsumeIngredients(enviornment) + fun filterConsumedIngredients(enviornment: E, requirements: Collection>) = result.filterConsumedIngredients(enviornment, requirements) abstract fun execute(input: E) class ItemResultHolder>(result: R) : ResultHolder(result) { From b96ed5f73bfbd299215fb18cd5d9c61e047c9fb1 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:40:01 -0600 Subject: [PATCH 406/500] Make progress result more general use, rename to WarmupResult, build out more utils --- .../entity/type/ProgressMultiblock.kt | 6 +- .../entity/type/power/IndustryEntity.kt | 2 +- .../newcrafting/MultiblockRecipeRegistry.kt | 23 +++-- .../newcrafting/input/FurnaceEnviornment.kt | 6 +- .../input/ItemResultEnviornment.kt | 2 - .../newcrafting/input/ProgressEnviornment.kt | 7 ++ .../newcrafting/input/RecipeEnviornment.kt | 3 + .../recipe/FurnaceMultiblockRecipe.kt | 11 +-- .../newcrafting/recipe/result/ItemResult.kt | 15 ++- .../recipe/result/ProgressResult.kt | 48 ---------- .../recipe/result/RecipeExecutionResult.kt | 11 +++ .../newcrafting/recipe/result/ResultHolder.kt | 92 ++++++++++++++++++- .../newcrafting/recipe/result/WarmupResult.kt | 37 ++++++++ 13 files changed, 178 insertions(+), 85 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt index 7bfc58d819..86cb6db82f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ProgressMultiblock.kt @@ -65,9 +65,11 @@ interface ProgressMultiblock { store.addAdditionalData(PROGRESS, DOUBLE, currentProgress) store.addAdditionalData(LAST_PROGRESS_TICK, LONG, lastProgressTick) } + } - fun formatProgress(color: TextColor): Component { - val percent = DecimalFormat("##.##").format(getCurrentProgress().roundToTenThousanth() * 100.0) + companion object { + fun formatProgress(color: TextColor, progress: Double): Component { + val percent = DecimalFormat("##.##").format(progress.roundToTenThousanth() * 100.0) return ofChildren(text(percent, color), text('%', HEColorScheme.HE_LIGHT_GRAY)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt index 69198a6a88..950eb25e7f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt @@ -32,7 +32,7 @@ abstract class IndustryEntity(data: PersistentMultiblockData, multiblock: Multib override var lastRecipe: NewMultiblockRecipe? = null override val progressManager: ProgressManager = ProgressManager(data) - override val tickingManager: TickingManager = TickingManager(20) + override val tickingManager: TickingManager = TickingManager(1) override val statusManager: StatusManager = StatusManager() final override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index 634da1c491..f92720d8f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -4,19 +4,22 @@ import io.papermc.paper.util.Tick import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.FurnaceMultiblockRecipe import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ProgressResult +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.WarmupResult import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import net.kyori.adventure.sound.Sound import org.bukkit.SoundCategory +import java.time.Duration import kotlin.reflect.KClass object MultiblockRecipeRegistry : IonServerComponent() { @@ -29,10 +32,12 @@ object MultiblockRecipeRegistry : IonServerComponent() { smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM), fuelItem = null, power = PowerRequirement(100), - result = ItemResult.simpleResult( - CustomItemRegistry.ENRICHED_URANIUM, - Sound.sound(NamespacedKeys.packKey("industry.centrifuge"), SoundCategory.BLOCKS, 1.0f, 1.0f) - ) + result = ResultHolder.of(WarmupResult( + duration = Duration.ofSeconds(5), + normalResult = ItemResult.simpleResult(CustomItemRegistry.ENRICHED_URANIUM), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.centrifuge"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateFurnace() )) val URANIUM_CORE_COMPRESSION = register(FurnaceMultiblockRecipe( @@ -41,10 +46,12 @@ object MultiblockRecipeRegistry : IonServerComponent() { smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM_CORE), fuelItem = null, power = PowerRequirement(100), - result = ProgressResult( + result = ResultHolder.of(WarmupResult( Tick.of(60L * 60L * 20L), - CustomItemRegistry.URANIUM_ROD.constructItemStack() - ) + ItemResult.simpleResult(CustomItemRegistry.URANIUM_ROD), + )) + .updateProgressText() + .updateFurnace() )) fun > register(recipe: R): R { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt index 61c4d47ae0..ad3fad3c7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt @@ -15,8 +15,8 @@ class FurnaceEnviornment( val furnaceInventory: FurnaceInventory, val powerStorage: PowerStorage, val tickingManager: TickedMultiblockEntityParent.TickingManager, - val progressManager: ProgressMultiblock.ProgressManager -) : ItemResultEnviornment { + val progress: ProgressMultiblock.ProgressManager +) : ItemResultEnviornment, ProgressEnviornment { constructor(entity: MultiblockEntity) : this( entity, entity.getInventory(0, 0, 0) as FurnaceInventory, @@ -44,6 +44,8 @@ class FurnaceEnviornment( return SlotModificationWrapper.furnaceResult(furnaceInventory) } + override fun getProgressManager(): ProgressMultiblock.ProgressManager = progress + override fun playSound(sound: Sound) { val furnaceLocation = furnaceInventory.holder?.location?.toCenterLocation() ?: throw IllegalStateException("Virtual furnace inventory passed to multiblock recipe! Don't do that!") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt index 0351683536..78df2e9471 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt @@ -1,11 +1,9 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.input -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import org.bukkit.inventory.ItemStack interface ItemResultEnviornment : RecipeEnviornment { - val multiblock: MultiblockEntity fun getResultItem(): ItemStack? fun getResultItemSlotModifier(): SlotModificationWrapper } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt new file mode 100644 index 0000000000..b3c25a6f63 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.input + +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock + +interface ProgressEnviornment : ItemResultEnviornment { + fun getProgressManager(): ProgressMultiblock.ProgressManager +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt index aeb0b9ff36..f99806e1e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt @@ -1,9 +1,12 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.input +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.kyori.adventure.sound.Sound import org.bukkit.inventory.ItemStack interface RecipeEnviornment { + val multiblock: MultiblockEntity + fun getItemSize(): Int fun getItem(index: Int): ItemStack? diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index d46a37e5f4..c5b54c8762 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.require import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper -import java.util.function.Consumer import kotlin.reflect.KClass /** @@ -23,10 +22,8 @@ class FurnaceMultiblockRecipe( smeltingItem: ItemRequirement?, fuelItem: ItemRequirement?, power: PowerRequirement, - result: ItemResult + private val result: ResultHolder> ) : NewMultiblockRecipe(identifier, clazz) { - val callbacks = mutableListOf>() - private val result = ResultHolder.of(result) override val requirements: Collection> = listOf( // Furnace smelting item @@ -48,11 +45,6 @@ class FurnaceMultiblockRecipe( ) ) - fun withCallback(consumer: Consumer): FurnaceMultiblockRecipe { - callbacks.add(consumer) - return this - } - override fun assemble(enviornment: FurnaceEnviornment) { if (!verifyAllRequirements(enviornment)) result if (!result.verifySpace(enviornment)) return @@ -62,6 +54,5 @@ class FurnaceMultiblockRecipe( .forEach { requirement -> requirement.consume(enviornment) } result.execute(enviornment) - callbacks.forEach { consumer -> consumer.accept(enviornment) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt index 2d7a910d95..5ae8c846dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt @@ -4,7 +4,6 @@ import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper -import net.kyori.adventure.sound.Sound import org.bukkit.Material import org.bukkit.inventory.ItemStack @@ -24,7 +23,7 @@ interface ItemResult : RecipeResult { /** * Executes the result **/ - fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) + fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper): RecipeExecutionResult /** * Gets the result item. @@ -32,17 +31,17 @@ interface ItemResult : RecipeResult { fun getResultItem(enviornment: E): ItemStack? companion object { - fun simpleResult(itemStack: ItemStack,sound: Sound? = null): SimpleResult = SimpleResult(itemStack, sound) - fun simpleResult(customItem: CustomItem,sound: Sound? = null): SimpleResult = SimpleResult(customItem.constructItemStack(), sound) - fun simpleResult(material: Material,sound: Sound? = null): SimpleResult = SimpleResult(ItemStack(material, 1), sound) + fun simpleResult(itemStack: ItemStack): SimpleResult = SimpleResult(itemStack) + fun simpleResult(customItem: CustomItem): SimpleResult = SimpleResult(customItem.constructItemStack()) + fun simpleResult(material: Material): SimpleResult = SimpleResult(ItemStack(material, 1)) } - class SimpleResult(private val item: ItemStack, val sound: Sound? = null) : ItemResult { + class SimpleResult(private val item: ItemStack) : ItemResult { override fun getResultItem(enviornment: E): ItemStack? = item override fun filterConsumedIngredients(enviornment: E, ingreidents: Collection>): Collection> = ingreidents - override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper) { + override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper): RecipeExecutionResult { slotModificationWrapper.addToSlot(item) - sound?.let { enviornment.playSound(it) } + return RecipeExecutionResult.SuccessExecutionResult } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt deleted file mode 100644 index 19ea0c5034..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ProgressResult.kt +++ /dev/null @@ -1,48 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result - -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper -import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.inventory.ItemStack -import java.time.Duration - -class ProgressResult(val duration: Duration, val resultItem: ItemStack) : ItemResult { - override fun verifySpace(enviornment: FurnaceEnviornment): Boolean { - val resultOccupant = enviornment.furnaceInventory.result ?: return true - if (resultOccupant.isEmpty) return true - if (!resultOccupant.isSimilar(resultItem)) return false - - val maxStackSize = resultItem.maxStackSize - return resultItem.amount + resultItem.amount <= maxStackSize - } - - override fun filterConsumedIngredients( - enviornment: FurnaceEnviornment, - ingreidents: Collection> - ): Collection> { - if (enviornment.progressManager.wouldComplete(duration)) return ingreidents - return ingreidents.filterNot { holder -> holder.requirement is ItemRequirement } - } - - override fun execute(enviornment: FurnaceEnviornment, slotModificationWrapper: SlotModificationWrapper) { - val complete = enviornment.progressManager.addProgress(duration) - - val multiblock = enviornment.multiblock - if (multiblock is StatusMultiblockEntity) multiblock.setStatus(enviornment.progressManager.formatProgress(NamedTextColor.RED)) - - if (!complete) return - - if (multiblock is StatusMultiblockEntity) multiblock.setStatus(enviornment.progressManager.formatProgress(NamedTextColor.GREEN)) - - enviornment.progressManager.reset() - slotModificationWrapper.addToSlot(resultItem) - } - - override fun getResultItem(enviornment: FurnaceEnviornment): ItemStack? { - if (!enviornment.progressManager.wouldComplete(duration)) return null - return resultItem - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt new file mode 100644 index 0000000000..285d990d1d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.kyori.adventure.text.Component + +sealed interface RecipeExecutionResult { + sealed interface Success : RecipeExecutionResult + + data object SuccessExecutionResult : Success + data class FailureExecutionResult(val reason: Component) : Success + data class ProgressExecutionResult(val newProgress: Double) : Success +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt index 0911ef57d7..1b74486322 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt @@ -1,22 +1,106 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock +import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock.Companion.formatProgress +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder +import net.kyori.adventure.sound.Sound +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.block.Furnace +import kotlin.math.roundToInt abstract class ResultHolder>(val result: R) { fun verifySpace(enviornment: E) = result.verifySpace(enviornment) fun filterConsumedIngredients(enviornment: E, requirements: Collection>) = result.filterConsumedIngredients(enviornment, requirements) abstract fun execute(input: E) - class ItemResultHolder>(result: R) : ResultHolder(result) { - override fun execute(enviornment: E) { - val slotModificationWrapper = enviornment.getResultItemSlotModifier() - result.execute(enviornment, slotModificationWrapper) + val callbacks = mutableListOf<(E, RecipeExecutionResult) -> Unit>() + + protected fun executeCallbacks(enviornment: E, result: RecipeExecutionResult) { + callbacks.forEach { t -> t.invoke(enviornment, result) } + } + + fun withCallback(callback: (E, RecipeExecutionResult) -> Unit): ResultHolder { + callbacks.add(callback) + return this + } + + fun playSound(sound: Sound, requireSuccess: Boolean): ResultHolder { + callbacks.add { enviornment: E, result: RecipeExecutionResult -> + if (requireSuccess && result is RecipeExecutionResult.SuccessExecutionResult) enviornment.playSound(sound) } + + return this + } + + fun updateFurnace(): ResultHolder { + callbacks.add { enviornment: E, executionResult: RecipeExecutionResult -> + val furnace = enviornment.multiblock.getInventory(0, 0, 0)?.holder as? Furnace ?: return@add + + // Extinguish the furnace if a failure + if (executionResult is RecipeExecutionResult.FailureExecutionResult) { + furnace.burnTime = 0 + furnace.update() + + return@add + } + + if (executionResult !is RecipeExecutionResult.Success) return@add + + // If progress is made on a recipe, update the furnace arrow to reflect + if (result is WarmupResult<*> && executionResult is RecipeExecutionResult.ProgressExecutionResult) { + furnace.burnTime = (200 - (executionResult.newProgress * 200).roundToInt()).toShort() + } else if (enviornment.multiblock is TickedMultiblockEntityParent) { + furnace.burnTime = (enviornment.multiblock as TickedMultiblockEntityParent).tickingManager.interval.toShort() + } + + furnace.update() + } + + return this + } + + fun updateProgressText(): ResultHolder { + callbacks.add { enviornment: E, result: RecipeExecutionResult -> + if (result !is RecipeExecutionResult.ProgressExecutionResult) return@add + + val entity = enviornment.multiblock + if (entity !is StatusMultiblockEntity) return@add + if (entity !is ProgressMultiblock) return@add + + entity.setStatus(formatProgress(NamedTextColor.BLUE, result.newProgress)) + } + + return this + } + + fun addCooldown(ticks: Int, requireSuccess: Boolean): ResultHolder { + callbacks.add { enviornment: E, result: RecipeExecutionResult -> + if (requireSuccess && result !is RecipeExecutionResult.SuccessExecutionResult) return@add + val entity = enviornment.multiblock + if (entity !is TickedMultiblockEntityParent) return@add + + entity.tickingManager.sleep(ticks) + } + + return this } companion object { fun of(result: ItemResult) = ItemResultHolder(result) + //TODO more results } + + class ItemResultHolder>(result: R) : ResultHolder(result) { + override fun execute(enviornment: E) { + val slotModificationWrapper = enviornment.getResultItemSlotModifier() + val result = result.execute(enviornment, slotModificationWrapper) + + executeCallbacks(enviornment, result) + } + } + } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt new file mode 100644 index 0000000000..12c7665164 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt @@ -0,0 +1,37 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ProgressEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder +import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import org.bukkit.inventory.ItemStack +import java.time.Duration + +class WarmupResult(val duration: Duration, val normalResult: ItemResult) : ItemResult { + override fun verifySpace(enviornment: E): Boolean { + return normalResult.verifySpace(enviornment) + } + + override fun filterConsumedIngredients( + enviornment: E, + ingreidents: Collection> + ): Collection> { + if (enviornment.getProgressManager().wouldComplete(duration)) return ingreidents + return ingreidents.filterNot { holder -> holder.requirement is ItemRequirement } + } + + override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper): RecipeExecutionResult { + val progressManager = enviornment.getProgressManager() + val complete = progressManager.addProgress(duration) + + if (!complete) return RecipeExecutionResult.ProgressExecutionResult(progressManager.getCurrentProgress()) + + progressManager.reset() + return normalResult.execute(enviornment, slotModificationWrapper) + } + + override fun getResultItem(enviornment: E): ItemStack? { + if (!enviornment.getProgressManager().wouldComplete(duration)) return null + return normalResult.getResultItem(enviornment) + } +} From 71cbd562be098576c1cba4433b7d20dcea231d62 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:01:58 -0600 Subject: [PATCH 407/500] rework results again, use a transaction and separate environment --- .../entity/type/power/IndustryEntity.kt | 2 +- .../newcrafting/MultiblockRecipeRegistry.kt | 4 +- .../recipe/FurnaceMultiblockRecipe.kt | 20 ++++++++-- .../newcrafting/recipe/result/ItemResult.kt | 20 +++++++--- .../newcrafting/recipe/result/RecipeResult.kt | 3 -- .../result/ResultExecutionEnviornment.kt | 25 +++++++++++++ .../newcrafting/recipe/result/ResultHolder.kt | 29 +++++++-------- .../newcrafting/recipe/result/WarmupResult.kt | 37 ++++++++++++------- 8 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt index 950eb25e7f..69198a6a88 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt @@ -32,7 +32,7 @@ abstract class IndustryEntity(data: PersistentMultiblockData, multiblock: Multib override var lastRecipe: NewMultiblockRecipe? = null override val progressManager: ProgressManager = ProgressManager(data) - override val tickingManager: TickingManager = TickingManager(1) + override val tickingManager: TickingManager = TickingManager(20) override val statusManager: StatusManager = StatusManager() final override val displayHandler = DisplayHandlers.newMultiblockSignOverlay( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt index f92720d8f7..aec0318693 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt @@ -31,7 +31,7 @@ object MultiblockRecipeRegistry : IonServerComponent() { clazz = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM), fuelItem = null, - power = PowerRequirement(100), + power = PowerRequirement(10), result = ResultHolder.of(WarmupResult( duration = Duration.ofSeconds(5), normalResult = ItemResult.simpleResult(CustomItemRegistry.ENRICHED_URANIUM), @@ -45,7 +45,7 @@ object MultiblockRecipeRegistry : IonServerComponent() { clazz = CompressorMultiblock.CompressorMultiblockEntity::class, smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM_CORE), fuelItem = null, - power = PowerRequirement(100), + power = PowerRequirement(10), result = ResultHolder.of(WarmupResult( Tick.of(60L * 60L * 20L), ItemResult.simpleResult(CustomItemRegistry.URANIUM_ROD), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt index c5b54c8762..c6d21dcfb9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt @@ -1,11 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe +import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultExecutionEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import kotlin.reflect.KClass @@ -49,10 +51,20 @@ class FurnaceMultiblockRecipe( if (!verifyAllRequirements(enviornment)) result if (!result.verifySpace(enviornment)) return - result - .filterConsumedIngredients(enviornment, getAllRequirements()) - .forEach { requirement -> requirement.consume(enviornment) } + val resultEnviornment = ResultExecutionEnviornment(enviornment, this) - result.execute(enviornment) + result.buildTransaction(enviornment, resultEnviornment) + + try { + resultEnviornment.requirements.forEach { requirement -> requirement.consume(enviornment) } + } catch (e: Throwable) { + IonServer.slF4JLogger.error("There was an error executing multiblock recipe $identifier: ${e.message}") + e.printStackTrace() + return + } + + // Once ingredients have been sucessfully consumed, execute the result + val executionResult = resultEnviornment.executeResult() + result.executeCallbacks(enviornment, executionResult) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt index 5ae8c846dc..0bde208545 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import org.bukkit.Material import org.bukkit.inventory.ItemStack @@ -23,7 +22,11 @@ interface ItemResult : RecipeResult { /** * Executes the result **/ - fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper): RecipeExecutionResult + fun buildTransaction( + recipeEnviornment: E, + resultEnviornment: ResultExecutionEnviornment, + slotModificationWrapper: SlotModificationWrapper + ) /** * Gets the result item. @@ -38,10 +41,15 @@ interface ItemResult : RecipeResult { class SimpleResult(private val item: ItemStack) : ItemResult { override fun getResultItem(enviornment: E): ItemStack? = item - override fun filterConsumedIngredients(enviornment: E, ingreidents: Collection>): Collection> = ingreidents - override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper): RecipeExecutionResult { - slotModificationWrapper.addToSlot(item) - return RecipeExecutionResult.SuccessExecutionResult + override fun buildTransaction( + recipeEnviornment: E, + resultEnviornment: ResultExecutionEnviornment, + slotModificationWrapper: SlotModificationWrapper + ) { + resultEnviornment.addResult { e -> + slotModificationWrapper.addToSlot(item) + RecipeExecutionResult.SuccessExecutionResult + } } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt index 60e7902458..02472ec6f0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt @@ -1,10 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder interface RecipeResult { - fun filterConsumedIngredients(enviornment: E, ingreidents: Collection>): Collection> - fun verifySpace(enviornment: E): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt new file mode 100644 index 0000000000..97b864fc76 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt @@ -0,0 +1,25 @@ +package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result + +import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.RecipeExecutionResult.SuccessExecutionResult + +class ResultExecutionEnviornment(val parent: E, val recipe: NewMultiblockRecipe) { + val requirements = recipe.getAllRequirements().toMutableList() + + private val results: MutableList<(E) -> RecipeExecutionResult> = mutableListOf() + + fun addResult(result: (E) -> RecipeExecutionResult) { + results.add(result) + } + + fun executeResult(): RecipeExecutionResult { + var result: RecipeExecutionResult = SuccessExecutionResult + + results.forEach { t -> + result = t.invoke(parent) + } + + return result + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt index 1b74486322..6c521b138f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblo import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.kyori.adventure.sound.Sound import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.Furnace @@ -14,22 +13,25 @@ import kotlin.math.roundToInt abstract class ResultHolder>(val result: R) { fun verifySpace(enviornment: E) = result.verifySpace(enviornment) - fun filterConsumedIngredients(enviornment: E, requirements: Collection>) = result.filterConsumedIngredients(enviornment, requirements) - abstract fun execute(input: E) - val callbacks = mutableListOf<(E, RecipeExecutionResult) -> Unit>() + /** + * Builds the result of the recipe in the result enviornment. Do not directly set the results in this function, it may result in duplications if errors arise elsewhere + **/ + abstract fun buildTransaction(input: E, resultEnviornment: ResultExecutionEnviornment) - protected fun executeCallbacks(enviornment: E, result: RecipeExecutionResult) { + val callbacks = mutableListOf<(E, RecipeExecutionResult?) -> Unit>() + + fun executeCallbacks(enviornment: E, result: RecipeExecutionResult?) { callbacks.forEach { t -> t.invoke(enviornment, result) } } - fun withCallback(callback: (E, RecipeExecutionResult) -> Unit): ResultHolder { + fun withCallback(callback: (E, RecipeExecutionResult?) -> Unit): ResultHolder { callbacks.add(callback) return this } fun playSound(sound: Sound, requireSuccess: Boolean): ResultHolder { - callbacks.add { enviornment: E, result: RecipeExecutionResult -> + callbacks.add { enviornment: E, result: RecipeExecutionResult? -> if (requireSuccess && result is RecipeExecutionResult.SuccessExecutionResult) enviornment.playSound(sound) } @@ -37,7 +39,7 @@ abstract class ResultHolder>(val result } fun updateFurnace(): ResultHolder { - callbacks.add { enviornment: E, executionResult: RecipeExecutionResult -> + callbacks.add { enviornment: E, executionResult: RecipeExecutionResult? -> val furnace = enviornment.multiblock.getInventory(0, 0, 0)?.holder as? Furnace ?: return@add // Extinguish the furnace if a failure @@ -64,7 +66,7 @@ abstract class ResultHolder>(val result } fun updateProgressText(): ResultHolder { - callbacks.add { enviornment: E, result: RecipeExecutionResult -> + callbacks.add { enviornment: E, result: RecipeExecutionResult? -> if (result !is RecipeExecutionResult.ProgressExecutionResult) return@add val entity = enviornment.multiblock @@ -78,7 +80,7 @@ abstract class ResultHolder>(val result } fun addCooldown(ticks: Int, requireSuccess: Boolean): ResultHolder { - callbacks.add { enviornment: E, result: RecipeExecutionResult -> + callbacks.add { enviornment: E, result: RecipeExecutionResult? -> if (requireSuccess && result !is RecipeExecutionResult.SuccessExecutionResult) return@add val entity = enviornment.multiblock if (entity !is TickedMultiblockEntityParent) return@add @@ -95,12 +97,9 @@ abstract class ResultHolder>(val result } class ItemResultHolder>(result: R) : ResultHolder(result) { - override fun execute(enviornment: E) { + override fun buildTransaction(enviornment: E, resultEnviornment: ResultExecutionEnviornment) { val slotModificationWrapper = enviornment.getResultItemSlotModifier() - val result = result.execute(enviornment, slotModificationWrapper) - - executeCallbacks(enviornment, result) + result.buildTransaction(enviornment, resultEnviornment, slotModificationWrapper) } } - } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt index 12c7665164..b949865b57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ProgressEnviornment import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import org.bukkit.inventory.ItemStack import java.time.Duration @@ -12,22 +11,32 @@ class WarmupResult(val duration: Duration, val normalRe return normalResult.verifySpace(enviornment) } - override fun filterConsumedIngredients( - enviornment: E, - ingreidents: Collection> - ): Collection> { - if (enviornment.getProgressManager().wouldComplete(duration)) return ingreidents - return ingreidents.filterNot { holder -> holder.requirement is ItemRequirement } - } - - override fun execute(enviornment: E, slotModificationWrapper: SlotModificationWrapper): RecipeExecutionResult { - val progressManager = enviornment.getProgressManager() + override fun buildTransaction( + recipeEnviornment: E, + resultEnviornment: ResultExecutionEnviornment, + slotModificationWrapper: SlotModificationWrapper + ) { + val progressManager = recipeEnviornment.getProgressManager() val complete = progressManager.addProgress(duration) - if (!complete) return RecipeExecutionResult.ProgressExecutionResult(progressManager.getCurrentProgress()) + if (!complete) { + resultEnviornment.requirements.removeAll { holder -> + holder.requirement is ItemRequirement + } + + resultEnviornment.addResult { e -> + RecipeExecutionResult.ProgressExecutionResult(progressManager.getCurrentProgress()) + } + + return + } + + resultEnviornment.addResult { e -> + progressManager.reset() + RecipeExecutionResult.SuccessExecutionResult + } - progressManager.reset() - return normalResult.execute(enviornment, slotModificationWrapper) + normalResult.buildTransaction(recipeEnviornment, resultEnviornment, slotModificationWrapper) } override fun getResultItem(enviornment: E): ItemStack? { From 09d6d0546f39a1d9f86b85a4fbab2cdf3011d85a Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:20:22 -0600 Subject: [PATCH 408/500] migrate recipes over --- .../crafting/MultiblockRecipeRegistry.kt | 226 ++++++++++++++++++ .../multiblock/crafting/MultiblockRecipes.kt | 178 -------------- .../crafting/ingredient/Consumable.kt | 46 ---- .../crafting/ingredient/FluidIngredient.kt | 26 -- .../crafting/ingredient/ItemIngredient.kt | 56 ----- .../ingredient/MultiblockRecipeIngredient.kt | 9 - .../crafting/ingredient/PowerIngredient.kt | 23 -- .../input/FurnaceEnviornment.kt | 4 +- .../input/ItemResultEnviornment.kt | 4 +- .../input/ProgressEnviornment.kt | 2 +- .../input/RecipeEnviornment.kt | 2 +- .../recipe/FurnaceMultiblockRecipe.kt | 91 ++++--- .../crafting/recipe/MultiblockRecipe.kt | 29 ++- .../recipe/ProcessingMultiblockRecipe.kt | 42 ---- .../crafting/recipe/ProviderRecipe.kt | 33 --- .../crafting/recipe/RecipeExecutionContext.kt | 25 -- .../recipe/requirement/Consumable.kt | 4 +- .../recipe/requirement/PowerRequirement.kt | 4 +- .../recipe/requirement/RecipeRequirement.kt | 2 +- .../recipe/requirement/RequirementHolder.kt | 6 +- .../item/GasCanisterRequirement.kt | 25 ++ .../requirement/item}/ItemRequirement.kt | 3 +- .../recipe/result/ItemResult.kt | 6 +- .../recipe/result/RecipeExecutionResult.kt | 2 +- .../crafting/recipe/result/RecipeResult.kt | 7 + .../result/ResultExecutionEnviornment.kt | 10 +- .../recipe/result/ResultHolder.kt | 6 +- .../recipe/result/WarmupResult.kt | 8 +- .../crafting/result/ActionResult.kt | 10 - .../multiblock/crafting/result/ItemResult.kt | 51 ---- .../crafting/result/MultiRecipeResult.kt | 23 -- .../crafting/result/MultiblockRecipeResult.kt | 9 - .../crafting/result/ProgressResult.kt | 27 --- .../multiblock/crafting/result/SoundResult.kt | 18 -- .../util/SlotModificationWrapper.kt | 2 +- .../multiblock/entity/type/RecipeEntity.kt | 36 --- .../type/RecipeProcessingMultiblockEntity.kt | 10 +- .../entity/type/power/IndustryEntity.kt | 6 +- .../newcrafting/MultiblockRecipeRegistry.kt | 68 ------ .../recipe/FurnaceMultiblockRecipe.kt | 70 ------ .../newcrafting/recipe/NewMultiblockRecipe.kt | 28 --- .../newcrafting/recipe/result/RecipeResult.kt | 7 - .../miscellaneous/registrations/Components.kt | 2 - 43 files changed, 375 insertions(+), 871 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipeRegistry.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/input/FurnaceEnviornment.kt (92%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/input/ItemResultEnviornment.kt (52%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/input/ProgressEnviornment.kt (73%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/input/RecipeEnviornment.kt (82%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/requirement/Consumable.kt (53%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/requirement/PowerRequirement.kt (61%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/requirement/RecipeRequirement.kt (50%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/requirement/RequirementHolder.kt (84%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/GasCanisterRequirement.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting/recipe/requirement => crafting/recipe/requirement/item}/ItemRequirement.kt (91%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/result/ItemResult.kt (86%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/result/RecipeExecutionResult.kt (79%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeResult.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/result/ResultExecutionEnviornment.kt (52%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/result/ResultHolder.kt (93%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/recipe/result/WarmupResult.kt (77%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/{newcrafting => crafting}/util/SlotModificationWrapper.kt (95%) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipeRegistry.kt new file mode 100644 index 0000000000..fd0d386dca --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipeRegistry.kt @@ -0,0 +1,226 @@ +package net.horizonsend.ion.server.features.multiblock.crafting + +import io.papermc.paper.util.Tick +import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry +import net.horizonsend.ion.server.features.gas.Gasses +import net.horizonsend.ion.server.features.multiblock.crafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.PowerRequirement +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.item.GasCanisterRequirement +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.item.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.ResultHolder +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.WarmupResult +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock +import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf +import net.kyori.adventure.sound.Sound +import org.bukkit.Material +import org.bukkit.SoundCategory +import java.time.Duration +import kotlin.reflect.KClass + +@Suppress("UNUSED") +object MultiblockRecipeRegistry : IonServerComponent() { + val recipes = mutableListOf>() + val byMultiblock = multimapOf>, MultiblockRecipe<*>>() + + val URANIUM_ENRICHMENT = register(FurnaceMultiblockRecipe( + identifier = "URANIUM_ENRICHMENT", + clazz = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + duration = Duration.ofSeconds(10), + normalResult = ItemResult.simpleResult(CustomItemRegistry.ENRICHED_URANIUM), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.centrifuge"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateFurnace() + )) + + val URANIUM_CORE_COMPRESSION = register(FurnaceMultiblockRecipe( + identifier = "URANIUM_CORE_COMPRESSION", + clazz = CompressorMultiblock.CompressorMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM_CORE), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L), + ItemResult.simpleResult(CustomItemRegistry.URANIUM_ROD), + )) + .updateProgressText() + .updateFurnace() + )) + + val STEEL_PRODUCTION = register(FurnaceMultiblockRecipe( + identifier = "STEEL_PRODUCTION", + clazz = GasFurnaceMultiblock.GasFurnaceMultiblockEntity::class, + smeltingItem = ItemRequirement.MaterialRequirement(Material.IRON_INGOT), + fuelItem = GasCanisterRequirement(Gasses.OXYGEN, 5), + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + duration = Duration.ofSeconds(10), + normalResult = ItemResult.simpleResult(CustomItemRegistry.STEEL_INGOT), + )) + .updateFurnace() + )) + + val REACTIVE_PLATING_PRESSING = register(FurnaceMultiblockRecipe( + identifier = "REACTIVE_PLATING_PRESSING", + clazz = PlatePressMultiblock.PlatePressMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.REACTIVE_PLATING), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L), + ItemResult.simpleResult(CustomItemRegistry.REACTIVE_CHASSIS), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.press"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val STEEL_PLATE_PRESSING = register(FurnaceMultiblockRecipe( + identifier = "STEEL_PLATE_PRESSING", + clazz = PlatePressMultiblock.PlatePressMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.STEEL_PLATE), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L), + ItemResult.simpleResult(CustomItemRegistry.STEEL_CHASSIS), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.press"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val FUEL_ROD_CORE_FABRICATION = register(FurnaceMultiblockRecipe( + identifier = "FUEL_ROD_CORE_FABRICATION", + clazz = FabricatorMultiblock.FabricatorMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.FUEL_ROD_CORE), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L * 2L), + ItemResult.simpleResult(CustomItemRegistry.FUEL_CELL), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.fabricate"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val FABRICATED_ASSEMBLY_FABRICATION = register(FurnaceMultiblockRecipe( + identifier = "FABRICATED_ASSEMBLY_FABRICATION", + clazz = FabricatorMultiblock.FabricatorMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.REACTIVE_ASSEMBLY), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L * 2L), + ItemResult.simpleResult(CustomItemRegistry.FABRICATED_ASSEMBLY), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.fabricate"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val REINFORCED_FRAME_FABRICATION = register(FurnaceMultiblockRecipe( + identifier = "REINFORCED_FRAME_FABRICATION", + clazz = FabricatorMultiblock.FabricatorMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.STEEL_ASSEMBLY), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L * 2L), + ItemResult.simpleResult(CustomItemRegistry.REINFORCED_FRAME), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.fabricate"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val CIRCUIT_BOARD_FABRICATION = register(FurnaceMultiblockRecipe( + identifier = "CIRCUIT_BOARD_FABRICATION", + clazz = CircuitfabMultiblock.CircuitfabMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.CIRCUITRY), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Tick.of(60L * 60L * 20L), + ItemResult.simpleResult(CustomItemRegistry.CIRCUIT_BOARD), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.fabricate"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val LOADED_SHELL_LOADING = register(FurnaceMultiblockRecipe( + identifier = "LOADED_SHELL_LOADING", + clazz = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.UNLOADED_SHELL), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Duration.ofSeconds(90), + ItemResult.simpleResult(CustomItemRegistry.LOADED_SHELL), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.load"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val UNCHARGED_SHELL_CHARGING = register(FurnaceMultiblockRecipe( + identifier = "UNCHARGED_SHELL_CHARGING", + clazz = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.UNCHARGED_SHELL), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Duration.ofSeconds(90), + ItemResult.simpleResult(CustomItemRegistry.CHARGED_SHELL), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.load"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + val ARSENAL_MISSILE_LOADING = register(FurnaceMultiblockRecipe( + identifier = "ARSENAL_MISSILE_LOADING", + clazz = MissileLoaderMultiblock.MissileLoaderMultiblockEntity::class, + smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.UNLOADED_ARSENAL_MISSILE), + fuelItem = null, + power = PowerRequirement(10), + result = ResultHolder.of(WarmupResult( + Duration.ofMinutes(60), + ItemResult.simpleResult(CustomItemRegistry.ARSENAL_MISSILE), + )) + .playSound(Sound.sound(NamespacedKeys.packKey("industry.mload"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) + .updateProgressText() + .updateFurnace() + )) + + fun > register(recipe: R): R { + recipes.add(recipe) + byMultiblock[recipe.entityType].add(recipe) + + return recipe + } + + fun getRecipesFor(entity: RecipeProcessingMultiblockEntity): Collection> { + @Suppress("UNCHECKED_CAST") + return byMultiblock[entity::class] as Collection> + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt deleted file mode 100644 index 30f58e2169..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/MultiblockRecipes.kt +++ /dev/null @@ -1,178 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting - -import io.papermc.paper.util.Tick -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.furnaceFuelIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.furnaceSmeltingIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.FurnaceMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.ProcessingMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.result.ItemResult.Companion.furnaceRecipeResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiRecipeResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.ProgressResult -import net.horizonsend.ion.server.features.multiblock.crafting.result.SoundResult -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.ammo.AmmoLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.ammo.MissileLoaderMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CircuitfabMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import org.bukkit.Material -import org.bukkit.SoundCategory -import org.bukkit.inventory.ItemStack -import java.util.LinkedList -import java.util.concurrent.ConcurrentHashMap -import kotlin.reflect.KClass - -@Suppress("UNUSED") -object MultiblockRecipes : IonServerComponent() { - private val recipes: ConcurrentHashMap, LinkedList>> = ConcurrentHashMap() - - val URANIUM_ENRICHMENT = registerRecipe(ProcessingMultiblockRecipe( - multiblock = CentrifugeMultiblock, - multiblockEntityClass = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.URANIUM, 1), - result = MultiRecipeResult( - furnaceRecipeResult(CustomItemRegistry.ENRICHED_URANIUM), - SoundResult("horizonsend:industry.centrifuge", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - resources = listOf(PowerIngredient(100)), - )) - - val URANIUM_CORE_COMPRESSION = registerRecipe(ProcessingMultiblockRecipe( - multiblock = CompressorMultiblock, - multiblockEntityClass = CompressorMultiblock.CompressorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.URANIUM_CORE, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.URANIUM_ROD)), - SoundResult("horizonsend:industry.compress", SoundCategory.BLOCKS, 1.0f, 1.0f) - ) - )) - - val STEEL_PRODUCTION = registerRecipe(FurnaceMultiblockRecipe( - multiblock = GasFurnaceMultiblock, - multiblockEntityClass = GasFurnaceMultiblock.GasFurnaceMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(ItemStack(Material.IRON_INGOT), 1), - fuel = furnaceFuelIngredient(CustomItemRegistry.GAS_CANISTER_OXYGEN, 5), - resources = listOf(PowerIngredient(100)), - result = furnaceRecipeResult(CustomItemRegistry.STEEL_INGOT) - )) - - val REACTIVE_PLATING_PRESSING = registerRecipe(ProcessingMultiblockRecipe( - multiblock = PlatePressMultiblock, - multiblockEntityClass = PlatePressMultiblock.PlatePressMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.REACTIVE_PLATING, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.REACTIVE_CHASSIS)), - SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f) - ) - )) - - val STEEL_PLATE_PRESSING = registerRecipe(ProcessingMultiblockRecipe( - multiblock = PlatePressMultiblock, - multiblockEntityClass = PlatePressMultiblock.PlatePressMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.STEEL_PLATE, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.STEEL_CHASSIS)), - SoundResult("horizonsend:industry.press", SoundCategory.BLOCKS, 1.0f, 1.0f) - ) - )) - - val FUEL_ROD_CORE_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.FUEL_ROD_CORE, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItemRegistry.FUEL_CELL)), - SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - val FABRICATED_ASSEMBLY_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.REACTIVE_ASSEMBLY, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItemRegistry.FABRICATED_ASSEMBLY)), - SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - val REINFORCED_FRAME_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( - multiblock = FabricatorMultiblock, - multiblockEntityClass = FabricatorMultiblock.FabricatorMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.STEEL_ASSEMBLY, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L * 2L), finalResult = furnaceRecipeResult(CustomItemRegistry.REINFORCED_FRAME)), - SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - val CIRCUIT_BOARD_FABRICATION = registerRecipe(ProcessingMultiblockRecipe( - multiblock = CircuitfabMultiblock, - multiblockEntityClass = CircuitfabMultiblock.CircuitfabMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.CIRCUITRY, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.CIRCUIT_BOARD)), - SoundResult("horizonsend:industry.fabricate", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - val LOADED_SHELL_LOADING = registerRecipe(ProcessingMultiblockRecipe( - multiblock = AmmoLoaderMultiblock, - multiblockEntityClass = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.UNLOADED_SHELL, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.LOADED_SHELL)), - SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - val UNCHARGED_SHELL_CHARGING = registerRecipe(ProcessingMultiblockRecipe( - multiblock = AmmoLoaderMultiblock, - multiblockEntityClass = AmmoLoaderMultiblock.AmmoLoaderMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.UNCHARGED_SHELL, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(90L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.CHARGED_SHELL)), - SoundResult("horizonsend:industry.load", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - val ARSENAL_MISSILE_LOADING = registerRecipe(ProcessingMultiblockRecipe( - multiblock = MissileLoaderMultiblock, - multiblockEntityClass = MissileLoaderMultiblock.MissileLoaderMultiblockEntity::class, - smelting = furnaceSmeltingIngredient(CustomItemRegistry.UNLOADED_ARSENAL_MISSILE, 1), - resources = listOf(PowerIngredient(100)), - result = MultiRecipeResult( - ProgressResult(Tick.of(60L * 60L * 20L), finalResult = furnaceRecipeResult(CustomItemRegistry.ARSENAL_MISSILE)), - SoundResult("horizonsend:industry.mload", SoundCategory.BLOCKS, 1.0f, 1.0f) - ), - )) - - private fun registerRecipe(recipe: MultiblockRecipe): MultiblockRecipe { - recipes.getOrPut(recipe.entityClass) { LinkedList() }.add(recipe) - - return recipe - } - - fun getRecipe(entity: T): MultiblockRecipe? { - @Suppress("UNCHECKED_CAST") - val recipesFor = (recipes[entity::class] as? LinkedList>) ?: return null - - return recipesFor.shuffled().firstOrNull { it.canExecute(entity) } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt deleted file mode 100644 index 33c4c9dbae..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/Consumable.kt +++ /dev/null @@ -1,46 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem -import net.horizonsend.ion.server.features.custom.items.type.GasCanister -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import org.bukkit.inventory.ItemStack - -interface Consumable { - fun checkRequirement(item: ItemStack?, context: RecipeExecutionContext): Boolean - - fun consumeIngredient(item: ItemStack, context: RecipeExecutionContext): Boolean - - class ItemConsumable(val itemStack: ItemStack, val amount: Int) : Consumable { - override fun checkRequirement(item: ItemStack?, context: RecipeExecutionContext): Boolean { - if (item == null) return false - if (!itemStack.isSimilar(item)) return false - - return item.amount >= amount - } - - override fun consumeIngredient(item: ItemStack, context: RecipeExecutionContext): Boolean { - item.amount -= amount - return true - } - } - - class GasCanisterConsumable(private val canister: GasCanister, val amount: Int) : Consumable { - override fun checkRequirement(item: ItemStack?, context: RecipeExecutionContext): Boolean { - if (item == null) return false - - val customItem = item.customItem - - if (customItem !is GasCanister) return false - if (customItem.gas != canister.gas) return false - - return canister.getFill(item) > amount - } - - override fun consumeIngredient(item: ItemStack, context: RecipeExecutionContext): Boolean { - val oldFill = canister.getFill(item) - canister.setFill(item, oldFill - amount) - return true - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt deleted file mode 100644 index b823f4c257..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/FluidIngredient.kt +++ /dev/null @@ -1,26 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidStoringEntity -import net.horizonsend.ion.server.features.transport.fluids.Fluid - -class FluidIngredient(val fluid: Fluid, val amount: Int) : MultiblockRecipeIngredient { - override fun checkRequirement(context: RecipeExecutionContext): Boolean { - val entity = context.entity - - if (entity !is FluidStoringEntity) return false - - return entity.fluidStores.any { it.internalStorage.getFluidType() == fluid && it.internalStorage.getAmount() >= amount } - } - - override fun consumeIngredient(context: RecipeExecutionContext): Boolean { - val entity = context.entity - - if (entity !is FluidStoringEntity) return false - - return (entity.fluidStores.firstOrNull { - it.internalStorage.getFluidType() == fluid && it.internalStorage.getAmount() >= amount - }?.internalStorage?.removeAmount(amount) ?: amount) == 0 - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt deleted file mode 100644 index 303d6d7c70..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/ItemIngredient.kt +++ /dev/null @@ -1,56 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.custom.items.type.GasCanister -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import org.bukkit.inventory.FurnaceInventory -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.ItemStack - -class ItemIngredient( - private val itemConsumable: Consumable, - private val cast: RecipeExecutionContext.() -> B?, - private val acquireItem: (B) -> ItemStack? -) : MultiblockRecipeIngredient { - override fun checkRequirement(context: RecipeExecutionContext): Boolean { - val acquiredItem = getItem(context) ?: return false - return itemConsumable.checkRequirement(acquiredItem, context) - } - - override fun consumeIngredient(context: RecipeExecutionContext): Boolean { - val acquiredItem = getItem(context) ?: return false - return itemConsumable.consumeIngredient(acquiredItem, context) - } - - fun getItem(context: RecipeExecutionContext): ItemStack? { - val inventory = cast.invoke(context) ?: return null - return acquireItem.invoke(inventory) - } - - companion object { - const val MAIN_FURNACE_STRING = "mainFurnace" - - fun furnaceFuelConsumable(consumable: Consumable) = ItemIngredient( - consumable, - { getLabeledInventory(MAIN_FURNACE_STRING) as? FurnaceInventory }, - { it.fuel } - ) - - fun furnaceFuelIngredient(item: ItemStack, amount: Int) = furnaceFuelConsumable(Consumable.ItemConsumable(item, amount)) - fun furnaceFuelIngredient(canister: GasCanister, amount: Int) = furnaceFuelConsumable(Consumable.GasCanisterConsumable(canister, amount)) - fun furnaceFuelIngredient(item: CustomItem, amount: Int) = furnaceFuelIngredient(item.constructItemStack(), amount) - - fun furnaceSmeltingIngredient(item: ItemStack, amount: Int) = ItemIngredient( - Consumable.ItemConsumable(item, amount), - { getLabeledInventory(MAIN_FURNACE_STRING) as? FurnaceInventory }, - { it.smelting } - ) - - fun furnaceSmeltingIngredient(item: CustomItem, amount: Int) = ItemIngredient( - Consumable.ItemConsumable(item.constructItemStack(), amount), - { getLabeledInventory(MAIN_FURNACE_STRING) as? FurnaceInventory }, - { it.smelting } - ) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt deleted file mode 100644 index 88bda4a523..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/MultiblockRecipeIngredient.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity - -interface MultiblockRecipeIngredient { - fun checkRequirement(context: RecipeExecutionContext): Boolean - fun consumeIngredient(context: RecipeExecutionContext): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt deleted file mode 100644 index a4aeb67208..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/ingredient/PowerIngredient.kt +++ /dev/null @@ -1,23 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.ingredient - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity - -class PowerIngredient(val amount: Int) : MultiblockRecipeIngredient { - override fun checkRequirement(context: RecipeExecutionContext): Boolean { - val entity = context.entity - - if (entity !is PoweredMultiblockEntity) return false - - return entity.powerStorage.getPower() >= amount - } - - override fun consumeIngredient(context: RecipeExecutionContext): Boolean { - val entity = context.entity - - if (entity !is PoweredMultiblockEntity) return false - - return entity.powerStorage.removePower(amount) == 0 - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/FurnaceEnviornment.kt similarity index 92% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/FurnaceEnviornment.kt index ad3fad3c7a..c50b5a8096 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/FurnaceEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/FurnaceEnviornment.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.input +package net.horizonsend.ion.server.features.multiblock.crafting.input +import net.horizonsend.ion.server.features.multiblock.crafting.util.SlotModificationWrapper import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper import net.kyori.adventure.sound.Sound import org.bukkit.inventory.FurnaceInventory import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/ItemResultEnviornment.kt similarity index 52% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/ItemResultEnviornment.kt index 78df2e9471..917d884c77 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ItemResultEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/ItemResultEnviornment.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.input +package net.horizonsend.ion.server.features.multiblock.crafting.input -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.horizonsend.ion.server.features.multiblock.crafting.util.SlotModificationWrapper import org.bukkit.inventory.ItemStack interface ItemResultEnviornment : RecipeEnviornment { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/ProgressEnviornment.kt similarity index 73% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/ProgressEnviornment.kt index b3c25a6f63..1744c6fcb8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/ProgressEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/ProgressEnviornment.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.input +package net.horizonsend.ion.server.features.multiblock.crafting.input import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/RecipeEnviornment.kt similarity index 82% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/RecipeEnviornment.kt index f99806e1e4..f78a5a0aa0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/input/RecipeEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/input/RecipeEnviornment.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.input +package net.horizonsend.ion.server.features.multiblock.crafting.input import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.kyori.adventure.sound.Sound diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt index bbdb887b8c..c0e7b85038 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/FurnaceMultiblockRecipe.kt @@ -1,45 +1,70 @@ package net.horizonsend.ion.server.features.multiblock.crafting.recipe -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import org.bukkit.inventory.FurnaceInventory -import org.bukkit.inventory.Inventory +import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.multiblock.crafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.PowerRequirement +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.RequirementHolder +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.item.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.ItemResult +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.ResultExecutionEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.ResultHolder +import net.horizonsend.ion.server.features.multiblock.crafting.util.SlotModificationWrapper +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity import kotlin.reflect.KClass /** - * Recipes that use both slots of a furnace + * A multiblock recipe that uses a furnace inventory. * - * Do NOT try to use this on a non-furnace inventory + * @param smeltingItem Requirement for the item in the top slot. If it is null, there will be a requirement for this slot to be empty. + * @param fuelItem Requirement for the item in the bottom slot. If it is null, there will be a requirement for this slot to be empty. **/ -class FurnaceMultiblockRecipe( - multiblock: EntityMultiblock, - multiblockEntityClass: KClass, - val smelting: MultiblockRecipeIngredient, - val fuel: MultiblockRecipeIngredient, - private val resources: List> = listOf(), - override val result: MultiblockRecipeResult -) : MultiblockRecipe(multiblock, multiblockEntityClass) { - override fun finalize(context: RecipeExecutionContext) { - result.execute(context) - } +class FurnaceMultiblockRecipe( + identifier: String, + clazz: KClass>, + smeltingItem: ItemRequirement?, + fuelItem: ItemRequirement?, + power: PowerRequirement, + private val result: ResultHolder> +) : MultiblockRecipe(identifier, clazz) { - override fun getLabeledInventories(context: RecipeExecutionContext): Map { - return mapOf(ItemIngredient.MAIN_FURNACE_STRING to context.entity.getInventory(0, 0, 0) as FurnaceInventory) - } + override val requirements: Collection> = listOf( + // Furnace smelting item + RequirementHolder.itemConsumable( + getter = { it.getItem(0) }, + requirement = smeltingItem ?: ItemRequirement.legacy(), + { SlotModificationWrapper.furnaceSmelting(it.furnaceInventory) } + ), + // Furnace fuel item + RequirementHolder.itemConsumable( + getter = { it.getItem(1) }, + requirement = fuelItem ?: ItemRequirement.legacy(), + { SlotModificationWrapper.furnaceFuel(it.furnaceInventory) } + ), + // Power requirement + RequirementHolder.simpleConsumable( + { it.powerStorage.getPower() }, + power + ) + ) - override fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean { - return smelting.checkRequirement(context) - && fuel.checkRequirement(context) - && resources.all { it.checkRequirement(context) } - } + override fun assemble(enviornment: FurnaceEnviornment) { + if (!verifyAllRequirements(enviornment)) result + if (!result.verifySpace(enviornment)) return + + val resultEnviornment = ResultExecutionEnviornment(enviornment, this) + + result.buildTransaction(enviornment, resultEnviornment) + + try { + resultEnviornment.requirements.forEach { requirement -> requirement.consume(enviornment) } + } catch (e: Throwable) { + IonServer.slF4JLogger.error("There was an error executing multiblock recipe $identifier: ${e.message}") + e.printStackTrace() + return + } - override fun consumeResources(context: RecipeExecutionContext): Boolean { - return smelting.consumeIngredient(context) - && fuel.consumeIngredient(context) - && resources.all { it.consumeIngredient(context) } + // Once ingredients have been sucessfully consumed, execute the result + val executionResult = resultEnviornment.executeResult() + result.executeCallbacks(enviornment, executionResult) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt index 4ede119dc7..fab2097a57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/MultiblockRecipe.kt @@ -1,21 +1,28 @@ package net.horizonsend.ion.server.features.multiblock.crafting.recipe -import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import org.bukkit.inventory.Inventory +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.Consumable +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.RequirementHolder +import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity +import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass -abstract class MultiblockRecipe(val multiblock: EntityMultiblock, val entityClass: KClass) { - abstract val result: MultiblockRecipeResult +abstract class MultiblockRecipe(val identifier: String, val entityType: KClass>) { + protected abstract val requirements: Collection> - abstract fun finalize(context: RecipeExecutionContext) + fun getConsumableRequirements(): Collection>> = requirements + .filter { holder -> holder.requirement is Consumable<* , *> } + .filterIsInstance>>() - abstract fun getLabeledInventories(context: RecipeExecutionContext): Map + fun getItemRequirements(): Collection> = requirements + .filter { it.dataTypeClass == ItemStack::class.java } + .filterIsInstance>() - abstract fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean + fun verifyAllRequirements(enviornment: E): Boolean = getAllRequirements().all { holder -> + holder.checkRequirement(enviornment) + } - abstract fun consumeResources(context: RecipeExecutionContext): Boolean + fun getAllRequirements(): Collection> = requirements - fun canExecute(entity: T): Boolean = checkResourcesAvailable(RecipeExecutionContext(this, entity)) + abstract fun assemble(input: E) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt deleted file mode 100644 index abe1f9228c..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProcessingMultiblockRecipe.kt +++ /dev/null @@ -1,42 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe - -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.MultiblockRecipeIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.PowerIngredient -import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import org.bukkit.inventory.FurnaceInventory -import org.bukkit.inventory.Inventory -import kotlin.reflect.KClass - -/** - * A multiblock recipe that takes one ingredient, and produces one result - * Usually furnace multiblocks with prismarine crystals occupying the bottom slot - * - * @param smelting, the input resource - * @param result, the result of the recipe - **/ -class ProcessingMultiblockRecipe( - multiblock: EntityMultiblock, - multiblockEntityClass: KClass, - val smelting: MultiblockRecipeIngredient, - override val result: MultiblockRecipeResult, - private val resources: List> = listOf(), -) : MultiblockRecipe(multiblock, multiblockEntityClass) { - override fun finalize(context: RecipeExecutionContext) { - result.execute(context) - } - - override fun getLabeledInventories(context: RecipeExecutionContext): Map { - return mapOf(ItemIngredient.MAIN_FURNACE_STRING to context.entity.getInventory(0, 0, 0) as FurnaceInventory) - } - - override fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean { - return smelting.checkRequirement(context) && resources.all { it.checkRequirement(context) } - } - - override fun consumeResources(context: RecipeExecutionContext): Boolean { - return smelting.consumeIngredient(context) && resources.all { it.consumeIngredient(context) } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt deleted file mode 100644 index 1763018b10..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/ProviderRecipe.kt +++ /dev/null @@ -1,33 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe - -import net.horizonsend.ion.server.features.multiblock.crafting.result.MultiblockRecipeResult -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import org.bukkit.inventory.Inventory -import kotlin.reflect.KClass - -class ProviderRecipe( - multiblock: EntityMultiblock, - entityClass: KClass, - override val result: MultiblockRecipeResult, - private val getLabeledInventories: RecipeExecutionContext.() -> Map, - private val checkResourcesAvailable: RecipeExecutionContext.() -> Boolean, - private val consumeResources: RecipeExecutionContext.() -> Boolean -) : MultiblockRecipe(multiblock, entityClass) { - - override fun consumeResources(context: RecipeExecutionContext): Boolean { - return consumeResources.invoke(context) - } - - override fun checkResourcesAvailable(context: RecipeExecutionContext): Boolean { - return checkResourcesAvailable.invoke(context) - } - - override fun getLabeledInventories(context: RecipeExecutionContext): Map { - return getLabeledInventories.invoke(context) - } - - override fun finalize(context: RecipeExecutionContext) { - result.execute(context) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt deleted file mode 100644 index eb73806d4f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/RecipeExecutionContext.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.recipe - -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import org.bukkit.inventory.Inventory - -class RecipeExecutionContext(val recipe: MultiblockRecipe, val entity: T) { - private var aborted: Boolean = false - private lateinit var inventories: Map - - fun getLabeledInventory(name: String): Inventory = inventories[name]!! - - fun execute() { - inventories = recipe.getLabeledInventories(this) - if (aborted) return - if (!recipe.checkResourcesAvailable(this)) return - if (aborted) return - if (!recipe.consumeResources(this)) return - if (aborted) return - recipe.finalize(this) - } - - fun abort() { - aborted = true - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/Consumable.kt similarity index 53% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/Consumable.kt index 3a898f4007..73b10a113d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/Consumable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/Consumable.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment /** * Represents a resource that is easily consumable from the enviornment, such as power diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/PowerRequirement.kt similarity index 61% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/PowerRequirement.kt index 2995213cea..af78caef70 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/PowerRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/PowerRequirement.kt @@ -1,6 +1,6 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.input.FurnaceEnviornment class PowerRequirement(val amount: Int) : Consumable { override fun ensureAvailable(resource: Int): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/RecipeRequirement.kt similarity index 50% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/RecipeRequirement.kt index e2e7e8f1f0..10b5c73a3b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RecipeRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/RecipeRequirement.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement interface RecipeRequirement { fun ensureAvailable(resource: T): Boolean diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/RequirementHolder.kt similarity index 84% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/RequirementHolder.kt index 67f5a9780b..a3a84837e1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/RequirementHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/RequirementHolder.kt @@ -1,7 +1,7 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.util.SlotModificationWrapper open class RequirementHolder>(val dataTypeClass: Class, val getter: (T) -> V, val requirement: R) { fun checkRequirement(enviornment: T): Boolean { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/GasCanisterRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/GasCanisterRequirement.kt new file mode 100644 index 0000000000..d10c26c578 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/GasCanisterRequirement.kt @@ -0,0 +1,25 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.item + +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.features.custom.items.type.GasCanister +import net.horizonsend.ion.server.features.gas.type.Gas +import org.bukkit.inventory.ItemStack + +class GasCanisterRequirement(val gas: Gas, val amount: Int) : ItemRequirement { + override fun matches(item: ItemStack?): Boolean { + if (item == null) return false + val customItem = item.customItem ?: return false + if (customItem !is GasCanister) return false + + return customItem.gas == gas && customItem.getComponent(CustomComponentTypes.GAS_STORAGE).getFill(item) >= amount + } + + override fun consume(item: ItemStack) { + val customItem = item.customItem as GasCanister + val component = customItem.getComponent(CustomComponentTypes.GAS_STORAGE) + + val currentFill = component.getFill(item) + component.setFill(item, customItem, currentFill - amount) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/ItemRequirement.kt similarity index 91% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/ItemRequirement.kt index e8a5d5c9b0..eaf1daec5c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/requirement/ItemRequirement.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/requirement/item/ItemRequirement.kt @@ -1,7 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.item import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.RecipeRequirement import org.bukkit.Material import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ItemResult.kt similarity index 86% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ItemResult.kt index 0bde208545..1f9e318867 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ItemResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ItemResult.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.result import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.horizonsend.ion.server.features.multiblock.crafting.input.ItemResultEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.util.SlotModificationWrapper import org.bukkit.Material import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeExecutionResult.kt similarity index 79% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeExecutionResult.kt index 285d990d1d..99278c16c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeExecutionResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeExecutionResult.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.result import net.kyori.adventure.text.Component diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeResult.kt new file mode 100644 index 0000000000..be485cb11d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/RecipeResult.kt @@ -0,0 +1,7 @@ +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.result + +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment + +interface RecipeResult { + fun verifySpace(enviornment: E): Boolean +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ResultExecutionEnviornment.kt similarity index 52% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ResultExecutionEnviornment.kt index 97b864fc76..d87188d7d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultExecutionEnviornment.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ResultExecutionEnviornment.kt @@ -1,10 +1,10 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.result -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.RecipeExecutionResult.SuccessExecutionResult +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.result.RecipeExecutionResult.SuccessExecutionResult -class ResultExecutionEnviornment(val parent: E, val recipe: NewMultiblockRecipe) { +class ResultExecutionEnviornment(val parent: E, val recipe: MultiblockRecipe) { val requirements = recipe.getAllRequirements().toMutableList() private val results: MutableList<(E) -> RecipeExecutionResult> = mutableListOf() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ResultHolder.kt similarity index 93% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ResultHolder.kt index 6c521b138f..d2430a6186 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/ResultHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/ResultHolder.kt @@ -1,11 +1,11 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.result +import net.horizonsend.ion.server.features.multiblock.crafting.input.ItemResultEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock.Companion.formatProgress import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ItemResultEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment import net.kyori.adventure.sound.Sound import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.Furnace diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/WarmupResult.kt similarity index 77% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/WarmupResult.kt index b949865b57..53c0345f57 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/WarmupResult.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/recipe/result/WarmupResult.kt @@ -1,8 +1,8 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result +package net.horizonsend.ion.server.features.multiblock.crafting.recipe.result -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.ProgressEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper +import net.horizonsend.ion.server.features.multiblock.crafting.input.ProgressEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.requirement.item.ItemRequirement +import net.horizonsend.ion.server.features.multiblock.crafting.util.SlotModificationWrapper import org.bukkit.inventory.ItemStack import java.time.Duration diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt deleted file mode 100644 index 524dded711..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ActionResult.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity - -fun interface ActionResult : MultiblockRecipeResult { - override fun canFit(context: RecipeExecutionContext): Boolean { - return true - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt deleted file mode 100644 index 5b3cbfc3e6..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ItemResult.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.custom.items.CustomItem -import net.horizonsend.ion.server.features.multiblock.crafting.ingredient.ItemIngredient.Companion.MAIN_FURNACE_STRING -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import org.bukkit.inventory.FurnaceInventory -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.ItemStack - -open class ItemResult( - private val result: ItemStack, - private val count: Int, - val outputInventory: String, - val check: (Inventory, ItemStack) -> Boolean, - val add: (Inventory, ItemStack) -> Unit, -) : MultiblockRecipeResult { - - override fun canFit(context: RecipeExecutionContext): Boolean { - val inv = context.getLabeledInventory(outputInventory) - return check.invoke(inv, result.asQuantity(count)) - } - - override fun execute(context: RecipeExecutionContext) { - val inv = context.getLabeledInventory(outputInventory) - add.invoke(inv, result.asQuantity(count)) - } - - companion object { - fun furnaceRecipeResult(resultItem: ItemStack, quantity: Int = 1) = ItemResult( - resultItem, - quantity, - MAIN_FURNACE_STRING, - check@ { inv, item -> - val resultSLot = (inv as FurnaceInventory).result ?: return@check true - if (!resultSLot.isSimilar(item)) return@check true - resultSLot.amount + quantity < resultItem.maxStackSize - }, - add@ { inv, item -> - val resultSLot = (inv as FurnaceInventory).result - if (resultSLot?.isSimilar(item) == true) { - resultSLot.amount += quantity - } - - if (resultSLot == null) inv.result = item - } - ) - - fun furnaceRecipeResult(resultItem: CustomItem, quantity: Int = 1) = furnaceRecipeResult(resultItem.constructItemStack(), quantity) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt deleted file mode 100644 index bb25f25eb1..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiRecipeResult.kt +++ /dev/null @@ -1,23 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity - -/** - * Wrap multiple result actions - **/ -class MultiRecipeResult( - val main: MultiblockRecipeResult, - vararg others: ActionResult -) : MultiblockRecipeResult { - private val actions = others.toList() - - override fun canFit(context: RecipeExecutionContext): Boolean { - return main.canFit(context) - } - - override fun execute(context: RecipeExecutionContext) { - main.execute(context) - actions.forEach { it.execute(context) } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt deleted file mode 100644 index 49410bfb1b..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/MultiblockRecipeResult.kt +++ /dev/null @@ -1,9 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity - -interface MultiblockRecipeResult { - fun canFit(context: RecipeExecutionContext): Boolean - fun execute(context: RecipeExecutionContext) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt deleted file mode 100644 index a0be7a637f..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/ProgressResult.kt +++ /dev/null @@ -1,27 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock -import java.time.Duration - -/** - * This item will convert into the result custom item after the amount of ticks provided (Assuming no lag and a 200 tick interval on the furnace) - **/ -class ProgressResult( - val duration: Duration, - val finalResult: MultiblockRecipeResult -) : MultiblockRecipeResult { - override fun canFit(context: RecipeExecutionContext): Boolean { - return finalResult.canFit(context) - } - - override fun execute(context: RecipeExecutionContext) { - val multiblock = context.entity as ProgressMultiblock - - if (multiblock.tickProgress(duration)) { - multiblock.progressManager.reset() - finalResult.execute(context) - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt deleted file mode 100644 index 0a7912e309..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/result/SoundResult.kt +++ /dev/null @@ -1,18 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.crafting.result - -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import org.bukkit.Registry -import org.bukkit.Sound -import org.bukkit.SoundCategory - -class SoundResult(val sound: String, private val soundCategory: SoundCategory, val volume: Float, val pitch: Float) : ActionResult { - - constructor(sound: Sound, soundCategory: SoundCategory, volume: Float, pitch: Float) : - this(Registry.SOUNDS.getKey(sound)?.key!!, soundCategory, volume, pitch) - - override fun execute(context: RecipeExecutionContext) { - val entity = context.entity - entity.world.playSound(entity.location, sound, soundCategory, volume, pitch) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/util/SlotModificationWrapper.kt similarity index 95% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/util/SlotModificationWrapper.kt index 7ae405f30a..55a0b65557 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/util/SlotModificationWrapper.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/crafting/util/SlotModificationWrapper.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.util +package net.horizonsend.ion.server.features.multiblock.crafting.util import com.google.common.base.Supplier import org.bukkit.inventory.FurnaceInventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt deleted file mode 100644 index 9cecdad368..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeEntity.kt +++ /dev/null @@ -1,36 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.entity.type - -import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.crafting.recipe.RecipeExecutionContext -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity - -/** - * Multiblock which processes multiblock recipes - **/ -interface RecipeEntity : ProgressMultiblock, SyncTickingMultiblockEntity { - fun T.getRecipe(): MultiblockRecipe? { - return MultiblockRecipes.getRecipe(this) - } - - override fun tick() { - return - executeRecipes() - } - - fun executeRecipes() { - this as MultiblockEntity - val recipe = this.getRecipe() - - if (recipe == null) { - tickingManager.sleep(500) - return - } - - if (recipe.canExecute(this)) return - - val context = RecipeExecutionContext(recipe, this) - context.execute() - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt index c127141a43..4888f7075c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/RecipeProcessingMultiblockEntity.kt @@ -1,16 +1,16 @@ package net.horizonsend.ion.server.features.multiblock.entity.type import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.newcrafting.MultiblockRecipeRegistry -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe +import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipeRegistry +import net.horizonsend.ion.server.features.multiblock.crafting.input.RecipeEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe interface RecipeProcessingMultiblockEntity { - var lastRecipe: NewMultiblockRecipe? + var lastRecipe: MultiblockRecipe? fun buildRecipeEnviornment(): E - fun getRecipesFor(): NewMultiblockRecipe? { + fun getRecipesFor(): MultiblockRecipe? { val enviornment = buildRecipeEnviornment() // Optimization step, avoid checking all recipes if (lastRecipe?.verifyAllRequirements(enviornment) == true) return lastRecipe diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt index 69198a6a88..746b886400 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/IndustryEntity.kt @@ -4,6 +4,8 @@ import net.horizonsend.ion.server.features.client.display.modular.DisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.crafting.input.FurnaceEnviornment +import net.horizonsend.ion.server.features.multiblock.crafting.recipe.MultiblockRecipe import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ProgressMultiblock @@ -14,8 +16,6 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusT import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent.TickingManager import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign @@ -29,7 +29,7 @@ abstract class IndustryEntity(data: PersistentMultiblockData, multiblock: Multib ProgressMultiblock, StatusTickedMultiblockEntity { - override var lastRecipe: NewMultiblockRecipe? = null + override var lastRecipe: MultiblockRecipe? = null override val progressManager: ProgressManager = ProgressManager(data) override val tickingManager: TickingManager = TickingManager(20) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt deleted file mode 100644 index aec0318693..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/MultiblockRecipeRegistry.kt +++ /dev/null @@ -1,68 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting - -import io.papermc.paper.util.Tick -import net.horizonsend.ion.server.IonServerComponent -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.FurnaceMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.NewMultiblockRecipe -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.WarmupResult -import net.horizonsend.ion.server.features.multiblock.type.industry.CentrifugeMultiblock -import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMultiblock -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.multimapOf -import net.kyori.adventure.sound.Sound -import org.bukkit.SoundCategory -import java.time.Duration -import kotlin.reflect.KClass - -object MultiblockRecipeRegistry : IonServerComponent() { - val recipes = mutableListOf>() - val byMultiblock = multimapOf>, NewMultiblockRecipe<*>>() - - val URANIUM_ENRICHMENT = register(FurnaceMultiblockRecipe( - identifier = "URANIUM_ENRICHMENT", - clazz = CentrifugeMultiblock.CentrifugeMultiblockEntity::class, - smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM), - fuelItem = null, - power = PowerRequirement(10), - result = ResultHolder.of(WarmupResult( - duration = Duration.ofSeconds(5), - normalResult = ItemResult.simpleResult(CustomItemRegistry.ENRICHED_URANIUM), - )) - .playSound(Sound.sound(NamespacedKeys.packKey("industry.centrifuge"), SoundCategory.BLOCKS, 1.0f, 1.0f), true) - .updateFurnace() - )) - - val URANIUM_CORE_COMPRESSION = register(FurnaceMultiblockRecipe( - identifier = "URANIUM_CORE_COMPRESSION", - clazz = CompressorMultiblock.CompressorMultiblockEntity::class, - smeltingItem = ItemRequirement.CustomItemRequirement(CustomItemRegistry.URANIUM_CORE), - fuelItem = null, - power = PowerRequirement(10), - result = ResultHolder.of(WarmupResult( - Tick.of(60L * 60L * 20L), - ItemResult.simpleResult(CustomItemRegistry.URANIUM_ROD), - )) - .updateProgressText() - .updateFurnace() - )) - - fun > register(recipe: R): R { - recipes.add(recipe) - byMultiblock[recipe.entityType].add(recipe) - - return recipe - } - - fun getRecipesFor(entity: RecipeProcessingMultiblockEntity): Collection> { - @Suppress("UNCHECKED_CAST") - return byMultiblock[entity::class] as Collection> - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt deleted file mode 100644 index c6d21dcfb9..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/FurnaceMultiblockRecipe.kt +++ /dev/null @@ -1,70 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe - -import net.horizonsend.ion.server.IonServer -import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.FurnaceEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.ItemRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.PowerRequirement -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ItemResult -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultExecutionEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result.ResultHolder -import net.horizonsend.ion.server.features.multiblock.newcrafting.util.SlotModificationWrapper -import kotlin.reflect.KClass - -/** - * A multiblock recipe that uses a furnace inventory. - * - * @param smeltingItem Requirement for the item in the top slot. If it is null, there will be a requirement for this slot to be empty. - * @param fuelItem Requirement for the item in the bottom slot. If it is null, there will be a requirement for this slot to be empty. - **/ -class FurnaceMultiblockRecipe( - identifier: String, - clazz: KClass>, - smeltingItem: ItemRequirement?, - fuelItem: ItemRequirement?, - power: PowerRequirement, - private val result: ResultHolder> -) : NewMultiblockRecipe(identifier, clazz) { - - override val requirements: Collection> = listOf( - // Furnace smelting item - RequirementHolder.itemConsumable( - getter = { it.getItem(0) }, - requirement = smeltingItem ?: ItemRequirement.legacy(), - { SlotModificationWrapper.furnaceSmelting(it.furnaceInventory) } - ), - // Furnace fuel item - RequirementHolder.itemConsumable( - getter = { it.getItem(1) }, - requirement = fuelItem ?: ItemRequirement.legacy(), - { SlotModificationWrapper.furnaceFuel(it.furnaceInventory) } - ), - // Power requirement - RequirementHolder.simpleConsumable( - { it.powerStorage.getPower() }, - power - ) - ) - - override fun assemble(enviornment: FurnaceEnviornment) { - if (!verifyAllRequirements(enviornment)) result - if (!result.verifySpace(enviornment)) return - - val resultEnviornment = ResultExecutionEnviornment(enviornment, this) - - result.buildTransaction(enviornment, resultEnviornment) - - try { - resultEnviornment.requirements.forEach { requirement -> requirement.consume(enviornment) } - } catch (e: Throwable) { - IonServer.slF4JLogger.error("There was an error executing multiblock recipe $identifier: ${e.message}") - e.printStackTrace() - return - } - - // Once ingredients have been sucessfully consumed, execute the result - val executionResult = resultEnviornment.executeResult() - result.executeCallbacks(enviornment, executionResult) - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt deleted file mode 100644 index 92f7099b62..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/NewMultiblockRecipe.kt +++ /dev/null @@ -1,28 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe - -import net.horizonsend.ion.server.features.multiblock.entity.type.RecipeProcessingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.Consumable -import net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.requirement.RequirementHolder -import org.bukkit.inventory.ItemStack -import kotlin.reflect.KClass - -abstract class NewMultiblockRecipe(val identifier: String, val entityType: KClass>) { - protected abstract val requirements: Collection> - - fun getConsumableRequirements(): Collection>> = requirements - .filter { holder -> holder.requirement is Consumable<* , *> } - .filterIsInstance>>() - - fun getItemRequirements(): Collection> = requirements - .filter { it.dataTypeClass == ItemStack::class.java } - .filterIsInstance>() - - fun verifyAllRequirements(enviornment: E): Boolean = getAllRequirements().all { holder -> - holder.checkRequirement(enviornment) - } - - fun getAllRequirements(): Collection> = requirements - - abstract fun assemble(input: E) -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt deleted file mode 100644 index 02472ec6f0..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/newcrafting/recipe/result/RecipeResult.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.horizonsend.ion.server.features.multiblock.newcrafting.recipe.result - -import net.horizonsend.ion.server.features.multiblock.newcrafting.input.RecipeEnviornment - -interface RecipeResult { - fun verifySpace(enviornment: E): Boolean -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index 68ca21dcf4..c5cf211f8f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -39,7 +39,6 @@ import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.MultiblockTicking -import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipes import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes @@ -140,7 +139,6 @@ val components: List = listOf( StationSieges, SolarSieges, - MultiblockRecipes, MultiblockRegistration, MultiblockAccess, MultiblockTicking, From aa45ab1f2614085c9db513fa824df88af4c1d363 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 18 Jan 2025 00:54:30 -0600 Subject: [PATCH 409/500] Store the sleep tick end as an epoch milli to make it independent of tick rate --- .../type/ticked/TickedMultiblockEntityParent.kt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt index bd7b0365f6..c65b05ebbb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/ticked/TickedMultiblockEntityParent.kt @@ -10,17 +10,15 @@ interface TickedMultiblockEntityParent { class TickingManager(val interval: Int) { private var currentTick: Int = 0 - private var sleepTicks: Int = 0 + + // Store the sleep tick end as an epoch milli to make it independent of tick rate + private var sleepTicksEnd: Long = 0 /** * Returns true if the current tick should be allowed to proceed **/ fun checkTickInterval(): Boolean { - if (sleepTicks >= 1) { - sleepTicks-- - - return false - } + if (System.currentTimeMillis() < sleepTicksEnd) return false currentTick++ @@ -34,11 +32,11 @@ interface TickedMultiblockEntityParent { } fun sleep(ticks: Int) { - sleepTicks += ticks + sleepTicksEnd = System.currentTimeMillis() + ticks } fun clearSleep() { - sleepTicks = 0 + sleepTicksEnd = 0 } } } From 53074136aa92de51d16662bef5ed75915f4dd240 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 18 Jan 2025 12:47:18 -0600 Subject: [PATCH 410/500] move solar panel cache --- .../transport/manager/ChunkTransportManager.kt | 2 +- .../transport/manager/ShipTransportManager.kt | 2 +- .../transport/manager/TransportManager.kt | 2 +- .../nodes/cache/PowerTransportCache.kt | 1 - .../cache/{solarpanel => }/SolarPanelCache.kt | 18 +++++++----------- .../features/transport/util/CacheType.kt | 2 +- 6 files changed, 11 insertions(+), 16 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/{solarpanel => }/SolarPanelCache.kt (82%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 3c000644b8..3d916bf0d9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -4,7 +4,7 @@ import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ChunkCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache +import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 9479db4da4..e483ae3fd0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ShipCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache +import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.nodes.inputs.ShipInputManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index ec992cc6af..869c86778c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache +import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager abstract class TransportManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index ce03014ca8..fddcddd862 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -6,7 +6,6 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSett import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder -import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt similarity index 82% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt index 525976b3b2..0615f9e6fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/solarpanel/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt @@ -1,9 +1,7 @@ -package net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel +package net.horizonsend.ion.server.features.transport.nodes.cache -import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings +import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder -import net.horizonsend.ion.server.features.transport.nodes.cache.NodeCacheFactory -import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getOrCacheNode @@ -13,9 +11,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import org.bukkit.Material.CRAFTING_TABLE -import org.bukkit.Material.DAYLIGHT_DETECTOR -import org.bukkit.Material.DIAMOND_BLOCK +import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.data.type.DaylightDetector @@ -23,9 +19,9 @@ import kotlin.math.roundToInt class SolarPanelCache(holder: CacheHolder) : TransportCache(holder) { override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() - .addSimpleNode(CRAFTING_TABLE, SolarPanelComponent.CraftingTable) - .addSimpleNode(DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) - .addSimpleNode(DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) + .addSimpleNode(Material.CRAFTING_TABLE, SolarPanelComponent.CraftingTable) + .addSimpleNode(Material.DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) + .addSimpleNode(Material.DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) .build() override val type: CacheType = CacheType.SOLAR_PANELS @@ -56,7 +52,7 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol val data = getBlockDataSafe(world, getX(detectorPosition), getY(detectorPosition), getZ(detectorPosition)) as? DaylightDetector ?: return 0 val powerRatio = data.power.toDouble() / data.maximumPower.toDouble() - val base = transportSettings().powerConfiguration.solarPanelTickPower * delta + val base = ConfigurationFiles.transportSettings().powerConfiguration.solarPanelTickPower * delta return (base * powerRatio * powerMultiplier).roundToInt() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index be4d823921..5a8efc8042 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.transport.util import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache -import net.horizonsend.ion.server.features.transport.nodes.cache.solarpanel.SolarPanelCache import net.horizonsend.ion.server.features.transport.util.CacheType.entries import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys From 187ce9353917b1056627950ecfd7674f30c68222 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 18 Jan 2025 13:13:49 -0600 Subject: [PATCH 411/500] Add item transport cache --- .../manager/ChunkTransportManager.kt | 2 + .../transport/manager/ShipTransportManager.kt | 4 +- .../transport/manager/TransportManager.kt | 2 + .../nodes/cache/FluidTransportCache.kt | 2 +- .../nodes/cache/ItemTransportCache.kt | 26 +++++ .../transport/nodes/cache/NodeCacheFactory.kt | 6 +- .../transport/nodes/types/ItemNode.kt | 96 +++++++++++++++++++ .../features/transport/util/CacheType.kt | 10 ++ .../miscellaneous/registrations/Components.kt | 5 +- 9 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 3d916bf0d9..b8557e8a95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ChunkCacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager @@ -18,6 +19,7 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } override val solarPanelManager = ChunkCacheHolder(this) { SolarPanelCache(it) } + override val itemPipeManager = ChunkCacheHolder(this) { ItemTransportCache(it) } // override val fluidNodeManager = ChunkCacheHolder(this) { FluidTransportCache(it) } override fun getInputProvider(): InputManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index e483ae3fd0..57836e133f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ShipCacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager @@ -15,7 +16,8 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { val inputManager = ShipInputManager(this) override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } - override val solarPanelManager: ShipCacheHolder = ShipCacheHolder(this) { SolarPanelCache(it) } + override val solarPanelManager = ShipCacheHolder(this) { SolarPanelCache(it) } + override val itemPipeManager = ShipCacheHolder(this) { ItemTransportCache(it) } // override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } init { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 869c86778c..e3adc45858 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager @@ -10,6 +11,7 @@ abstract class TransportManager { abstract val extractorManager: ExtractorManager abstract val powerNodeManager: CacheHolder abstract val solarPanelManager: CacheHolder + abstract val itemPipeManager: CacheHolder // abstract val fluidNodeManager: CacheHolder abstract fun getInputProvider(): InputManager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index af6677dc93..79880c57b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -33,7 +33,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .addSimpleNode(WAXED_EXPOSED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_EXPOSED_CHISELED_COPPER) } .addSimpleNode(WAXED_WEATHERED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_WEATHERED_CHISELED_COPPER) } .addSimpleNode(WAXED_OXIDIZED_COPPER) { FluidNode.FluidJunctionNode(WAXED_OXIDIZED_COPPER) } - .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { FluidNode.FluidJunctionNode(CRAFTING_TABLE) } // All unwaxed chiseled are a single channel + .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { _, _ -> FluidNode.FluidJunctionNode(CRAFTING_TABLE) } // All unwaxed chiseled are a single channel .addSimpleNode(CRAFTING_TABLE, FluidNode.FluidExtractorNode) .addSimpleNode(Material.FLETCHING_TABLE, FluidNode.FluidInputNode) .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt new file mode 100644 index 0000000000..817beb233d --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.transport.nodes.cache + +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode +import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Material +import org.bukkit.craftbukkit.block.impl.CraftGrindstone + +class ItemTransportCache(holder: CacheHolder): TransportCache(holder) { + override val type: CacheType = CacheType.FLUID + override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } + .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } + .addSimpleNode(Material.TINTED_GLASS, ItemNode.WildcardSolidGlassNode) + .addSimpleNode(Material.GLASS, ItemNode.WildcardSolidGlassNode) + .addSimpleNode(Material.GLASS_PANE, ItemNode.WildcardPaneGlassNode) + .addDataHandler(Material.GRINDSTONE) { data, key -> ItemNode.ItemMergeNode } + .build() + + override fun tickExtractor(location: BlockKey, delta: Double) { + + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index da92aecc55..4cf3c892f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -29,8 +29,8 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map, constructor: (BlockKey) -> Node): Builder { - for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, key -> constructor(key) } + fun addSimpleNode(materials: Iterable, constructor: (BlockKey, Material) -> Node): Builder { + for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) } return this } @@ -49,6 +49,8 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map = ADJACENT_BLOCK_FACES.minus(backwards) + + override val pathfindingResistance: Double = 1.0 + } + + data class PaneGlassNode(override val channel: PipeChannel) : ItemNode, ChanneledItemNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = channelCheck(other) //TODO + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = channelCheck(other) //TODO + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override val pathfindingResistance: Double = 1.0 + } + + data object WildcardSolidGlassNode : ItemNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override val pathfindingResistance: Double = 1.0 + } + + data object WildcardPaneGlassNode : ItemNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override val pathfindingResistance: Double = 1.0 + } + + data object ItemMergeNode : ItemNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override val pathfindingResistance: Double = 1.0 + } + + enum class PipeChannel(val solidMaterial: Material, val paneMaterial: Material, val textColor: TextColor) { + WHITE(Material.WHITE_STAINED_GLASS, Material.WHITE_STAINED_GLASS_PANE, NamedTextColor.WHITE), + LIGHT_GRAY(Material.LIGHT_GRAY_STAINED_GLASS, Material.LIGHT_GRAY_STAINED_GLASS_PANE, NamedTextColor.GRAY), + GRAY(Material.GRAY_STAINED_GLASS, Material.GRAY_STAINED_GLASS_PANE, NamedTextColor.DARK_GRAY), + BLACK(Material.BLACK_STAINED_GLASS, Material.BLACK_STAINED_GLASS_PANE, NamedTextColor.BLACK), + BROWN(Material.BROWN_STAINED_GLASS, Material.BROWN_STAINED_GLASS_PANE, fromHexString("#6F4E37")!!), + RED(Material.RED_STAINED_GLASS, Material.RED_STAINED_GLASS_PANE, NamedTextColor.RED), + ORANGE(Material.ORANGE_STAINED_GLASS, Material.ORANGE_STAINED_GLASS_PANE, NamedTextColor.GOLD), + YELLOW(Material.YELLOW_STAINED_GLASS, Material.YELLOW_STAINED_GLASS_PANE, NamedTextColor.YELLOW), + LIME(Material.LIME_STAINED_GLASS, Material.LIME_STAINED_GLASS_PANE, NamedTextColor.GREEN), + GREEN(Material.GREEN_STAINED_GLASS, Material.GREEN_STAINED_GLASS_PANE, NamedTextColor.DARK_GREEN), + CYAN(Material.CYAN_STAINED_GLASS, Material.CYAN_STAINED_GLASS_PANE, NamedTextColor.DARK_AQUA), + LIGHT_BLUE(Material.LIGHT_BLUE_STAINED_GLASS, Material.LIGHT_BLUE_STAINED_GLASS_PANE, NamedTextColor.AQUA), + BLUE(Material.BLUE_STAINED_GLASS, Material.BLUE_STAINED_GLASS_PANE, NamedTextColor.BLUE), + PURPLE(Material.PURPLE_STAINED_GLASS, Material.PURPLE_STAINED_GLASS_PANE, NamedTextColor.DARK_PURPLE), + MAGENTA(Material.MAGENTA_STAINED_GLASS, Material.MAGENTA_STAINED_GLASS_PANE, NamedTextColor.LIGHT_PURPLE), + PINK(Material.PINK_STAINED_GLASS, Material.PINK_STAINED_GLASS_PANE, fromHexString("#FFC0CB")!!), + + ; + + companion object { + private val byMaterial: Map = mutableMapOf( + *entries.map { channel -> channel.solidMaterial to channel }.toTypedArray(), + *entries.map { channel -> channel.paneMaterial to channel }.toTypedArray(), + ) + + operator fun get(material: Material) = byMaterial[material] + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index 5a8efc8042..52a6626325 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.util import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache @@ -40,6 +41,15 @@ enum class CacheType(val namespacedKey: NamespacedKey) { // return ship.transportManager.fluidNodeManager.cache } }, + ITEMS(NamespacedKeys.ITEM_TRANSPORT) { + override fun get(chunk: IonChunk): ItemTransportCache { + return chunk.transportNetwork.itemPipeManager.cache + } + + override fun get(ship: ActiveStarship): ItemTransportCache { + return ship.transportManager.itemPipeManager.cache + } + }, ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index c5cf211f8f..eb31313733 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -39,10 +39,7 @@ import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.MultiblockRegistration import net.horizonsend.ion.server.features.multiblock.MultiblockTicking -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockAccess -import net.horizonsend.ion.server.features.multiblock.newer.MultiblockRegistration -import net.horizonsend.ion.server.features.multiblock.type.crafting.MultiblockRecipes -import net.horizonsend.ion.server.features.multiblock.newcrafting.MultiblockRecipeRegistry +import net.horizonsend.ion.server.features.multiblock.crafting.MultiblockRecipeRegistry import net.horizonsend.ion.server.features.nations.NationsBalancing import net.horizonsend.ion.server.features.nations.NationsMap import net.horizonsend.ion.server.features.nations.NationsMasterTasks From ec0762dfa047d0b2a58c643e292c738259dd8d6b Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Mon, 20 Jan 2025 00:13:51 -0600 Subject: [PATCH 412/500] Store ship nodes & multiblocks in relative positions --- .../ion/server/command/admin/WorldCommand.kt | 6 +- .../server/command/misc/MultiblockCommand.kt | 31 ++--- .../command/misc/TransportDebugCommand.kt | 24 ++-- .../command/starship/StarshipDebugCommand.kt | 34 ----- .../multiblock/entity/MultiblockEntity.kt | 101 ++++++--------- .../entity/linkages/MultiblockLinkage.kt | 1 - .../entity/linkages/MultiblockLinkages.kt | 17 --- .../entity/linkages/ShipLinkageManager.kt | 23 +--- .../type/fluids/BasicFluidStoringEntity.kt | 2 +- .../entity/type/fluids/FluidStoringEntity.kt | 13 -- .../entity/type/power/SimplePoweredEntity.kt | 2 +- .../linkage/MultiblockLinkageHolder.kt | 75 +++++++++++ .../multiblock/manager/MultiblockManager.kt | 52 +++++--- .../manager/ShipMultiblockManager.kt | 122 +++++++----------- .../manager/WorldMultiblockManager.kt | 3 + .../multiblock/type/drills/DrillMultiblock.kt | 2 +- .../type/fluid/CanisterVentMultiblock.kt | 2 +- .../type/fluid/ElectrolysisMultiblock.kt | 2 +- .../CanisterGasCollectorMultiblock.kt | 2 +- .../collector/PipedGasCollectorMultiblock.kt | 2 +- .../type/misc/ItemSplitterMultiblock.kt | 2 +- .../multiblock/type/misc/MobDefender.kt | 11 +- .../type/power/storage/PowerBankMultiblock.kt | 4 + .../ion/server/features/starship/Starship.kt | 55 +++++++- .../starship/active/ActiveStarshipFactory.kt | 3 + .../subsystem/misc/MiningLaserSubsystem.kt | 2 +- .../server/features/transport/NewTransport.kt | 6 +- .../manager/ChunkTransportManager.kt | 46 ++----- .../transport/manager/ShipTransportManager.kt | 35 +++-- .../transport/manager/TransportManager.kt | 9 +- .../extractors/ShipExtractorManager.kt | 35 ++--- .../transport/manager/holders/CacheHolder.kt | 2 +- .../manager/holders/ChunkCacheHolder.kt | 1 + .../manager/holders/ShipCacheHolder.kt | 17 ++- .../transport/nodes/cache/TransportCache.kt | 13 +- 35 files changed, 386 insertions(+), 371 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt index e8a4862486..aaf118ef4b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/WorldCommand.kt @@ -206,9 +206,9 @@ object WorldCommand : SLCommand() { ) { val entity = entities[it] - ofChildren(text(entity.javaClass.simpleName), space(), bracketed(text("${entity.x} ${entity.y} ${entity.z}")),) - .clickEvent(ClickEvent.runCommand("/tp ${entity.x} ${entity.y} ${entity.z}")) - .hoverEvent(text("/tp ${entity.x} ${entity.y} ${entity.z}")) + ofChildren(text(entity.javaClass.simpleName), space(), bracketed(text("${entity.globalVec3i.x} ${entity.globalVec3i.y} ${entity.globalVec3i.z}")),) + .clickEvent(ClickEvent.runCommand("/tp ${entity.globalVec3i.x} ${entity.globalVec3i.y} ${entity.globalVec3i.z}")) + .hoverEvent(text("/tp ${entity.globalVec3i.x} ${entity.globalVec3i.y} ${entity.globalVec3i.z}")) } sender.information("Entities:") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt index dc72d6c359..8bfaa99f67 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/MultiblockCommand.kt @@ -191,10 +191,8 @@ object MultiblockCommand : SLCommand() { }) if (visual == true) { - for ((key, _) in entities) { - val vec = toVec3i(key) - - sender.highlightBlock(vec, 30L) + for ((_, entity) in entities) { + sender.highlightBlock(entity.globalVec3i, 30L) } } @@ -209,24 +207,21 @@ object MultiblockCommand : SLCommand() { val manager = ship.multiblockManager val entities = manager.getAllMultiblockEntities().toList() - sender.sendMessage( - formatPaginatedMenu( - entities.size, - "/ionchunk dumpentities ${visual ?: false}", - page ?: 1, - ) { index -> - val (key, entity) = entities[index] + sender.sendMessage(formatPaginatedMenu( + entities.size, + "/ionchunk dumpentities ${visual ?: false}", + page ?: 1, + ) { index -> + val (key, entity) = entities[index] - val vec = toVec3i(key) + val vec = toVec3i(key) - text("$vec : $entity") - }) + text("$vec : $entity") + }) if (visual == true) { - for ((key, _) in entities) { - val vec = toVec3i(key) - - sender.highlightBlock(vec, 30L) + for ((_, entity) in entities) { + sender.highlightBlock(entity.globalVec3i, 30L) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 702bcc285d..0539e3e6a8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -1,7 +1,6 @@ package net.horizonsend.ion.server.command.misc import co.aikar.commands.annotation.CommandAlias -import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission import co.aikar.commands.annotation.Subcommand import io.papermc.paper.util.StacktraceDeobfuscator @@ -11,6 +10,7 @@ import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.command.admin.IonChunkCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks +import net.horizonsend.ion.server.features.transport.nodes.cache.CacheState import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode @@ -104,31 +104,33 @@ object TransportDebugCommand : SLCommand() { } @Subcommand("dump nodes chunk") - @CommandCompletion("power") /* |item|gas") */ fun dumpNodesChunk(sender: Player, network: CacheType) { val ionChunk = sender.chunk.ion() val grid = network.get(ionChunk) + .getRawCache() + .filter { entry -> entry.value !is CacheState.Empty } - sender.information("${grid.getRawCache().size} covered position(s).") - sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") + sender.information("${grid.size} covered position(s).") + sender.information("${grid.values.distinct().size} unique node(s).") - grid.getRawCache().forEach { (t, _) -> + grid.forEach { (t, _) -> val vec = toVec3i(t) sender.highlightBlock(vec, 50L) } } @Subcommand("dump nodes ship") - @CommandCompletion("power") /* |item|gas") */ fun dumpNodesShip(sender: Player, network: CacheType) { val ship = getStarshipRiding(sender) val grid = network.get(ship) + .getRawCache() + .filter { entry -> entry.value !is CacheState.Empty } - sender.information("${grid.getRawCache().size} covered position(s).") - sender.information("${grid.getRawCache().values.distinct().size} unique node(s).") + sender.information("${grid.size} covered position(s).") + sender.information("${grid.values.distinct().size} unique node(s).") - grid.getRawCache().forEach { (t, _) -> - val vec = toVec3i(t) + grid.forEach { (localKey, _) -> + val vec = ship.transportManager.getGlobalCoordinate(toVec3i(localKey)) sender.highlightBlock(vec, 50L) } } @@ -153,7 +155,7 @@ object TransportDebugCommand : SLCommand() { sender.information("${extractors.getExtractors().size} covered position(s).") extractors.getExtractors().forEach { extractor -> - sender.highlightBlock(toVec3i(extractor.pos), 50L) + sender.highlightBlock(ship.transportManager.getGlobalCoordinate(toVec3i(extractor.pos)), 50L) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt index 1c681cb43e..24c7a12d5d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/starship/StarshipDebugCommand.kt @@ -3,16 +3,13 @@ package net.horizonsend.ion.server.command.starship import co.aikar.commands.annotation.CommandAlias import co.aikar.commands.annotation.CommandCompletion import co.aikar.commands.annotation.CommandPermission -import co.aikar.commands.annotation.Optional import co.aikar.commands.annotation.Subcommand import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError -import net.horizonsend.ion.common.utils.text.formatPaginatedMenu import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.ai.module.targeting.TargetingModule -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.misc.UnusedSoldShipPurge import net.horizonsend.ion.server.features.starship.DeactivatedPlayerStarships import net.horizonsend.ion.server.features.starship.active.ActiveStarships @@ -27,8 +24,6 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile. import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.helixAroundVector -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.kyori.adventure.text.Component import org.bukkit.Color import org.bukkit.Location import org.bukkit.Particle @@ -232,33 +227,4 @@ object StarshipDebugCommand : SLCommand() { abstract fun apply(controller: ActivePlayerController) } - - @Subcommand("dumpEntities") - fun onDumpEntities(sender: Player, @Optional visual: Boolean?, @Optional page: Int?) { - val manager = getStarshipRiding(sender).multiblockManager - val entities = manager.getAllMultiblockEntities().toList() - - sender.sendMessage(formatPaginatedMenu( - entities.size, - "/ionchunk dumpentities ${visual ?: false}", - page ?: 1, - ) { index -> - val (key, entity) = entities[index] - - val vec = toVec3i(key) - - Component.text("$vec : $entity") - }) - - if (visual == true) { - for ((key, _) in entities) { - val vec = toVec3i(key) - - sender.highlightBlock(vec, 30L) - } - } - - sender.information("Sync Ticked: ${manager.syncTickingMultiblockEntities}") - sender.information("Async Ticked: ${manager.asyncTickingMultiblockEntities}") - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index de40a8adb8..9cd3c22fee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -2,15 +2,14 @@ package net.horizonsend.ion.server.features.multiblock.entity import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkage import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.linkage.MultiblockLinkageHolder import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializable import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -18,7 +17,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.getRelativeIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.isBlockLoaded import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import org.bukkit.Location import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.BlockFace @@ -26,9 +24,6 @@ import org.bukkit.block.Sign import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder import org.bukkit.persistence.PersistentDataAdapterContext -import java.util.UUID -import java.util.function.Supplier -import kotlin.reflect.KClass /** * @param manager The multiblock manager that this is registered to @@ -43,44 +38,47 @@ import kotlin.reflect.KClass **/ abstract class MultiblockEntity( var manager: MultiblockManager, + open val multiblock: Multiblock, - var x: Int, - var y: Int, - var z: Int, var world: World, + var localOffsetX: Int, + var localOffsetY: Int, + var localOffsetZ: Int, + var structureDirection: BlockFace ): PDCSerializable, DisplayHandlerHolder { private var lastRetrieved = System.currentTimeMillis() - /** Gets the time since this value was last retrieved */ - protected val deltaTMS: Long get() { - val time = System.currentTimeMillis() - val delta = time - lastRetrieved - lastRetrieved = time - - return delta - } - /** Mark this entity as having been removed */ var removed: Boolean = false final override val isAlive: Boolean get() = !removed override val persistentDataType: PersistentMultiblockData.Companion = PersistentMultiblockData.Companion - val position: BlockKey get() = toBlockKey(x, y, z) /** - * Returns the origin of this multiblock as a Location + * Returns the location of this multiblock, relative to the global origin, as a Location **/ - val location get() = Location(world, x.toDouble(), y.toDouble(), z.toDouble()) + val location get() = globalVec3i.toLocation(world) /** * Returns the origin of this multiblock as a Vec3i **/ - val vec3i get() = Vec3i(x, y, z) + val localVec3i get() = Vec3i(localOffsetX, localOffsetY, localOffsetZ) + val globalVec3i get() = manager.getGlobalCoordinate(localVec3i) + + val localBlockKey: BlockKey get() = toBlockKey(localOffsetX, localOffsetY, localOffsetZ) + val globalBlockKey: BlockKey get() = toBlockKey(globalVec3i) + + /** Gets the time since this value was last retrieved */ + protected val deltaTMS: Long get() { + val time = System.currentTimeMillis() + val delta = time - lastRetrieved + lastRetrieved = time - val locationKey get() = toBlockKey(x, y, z) + return delta + } fun processRemoval() { removed = true @@ -96,7 +94,7 @@ abstract class MultiblockEntity( /** Removes this multiblock entity */ fun remove() { - manager.removeMultiblockEntity(x, y, z) + manager.removeMultiblockEntity(localOffsetX, localOffsetY, localOffsetZ) } /** Logic to be run upon the unloading of the chunk holding this entity */ @@ -126,7 +124,7 @@ abstract class MultiblockEntity( * This data is serialized and stored on the chunk when not loaded. **/ fun store(): PersistentMultiblockData { - val store = PersistentMultiblockData(x, y, z, multiblock, structureDirection) + val store = PersistentMultiblockData(localOffsetX, localOffsetY, localOffsetZ, multiblock, structureDirection) storeAdditionalData(store, store.getAdditionalDataRaw().adapterContext) return store @@ -143,7 +141,7 @@ abstract class MultiblockEntity( fun isSignLoaded(): Boolean { val signDirection = structureDirection.oppositeFace - val signLoc = Vec3i(x, y, z) + Vec3i(signDirection.modX, 0, signDirection.modZ) + val signLoc = globalVec3i + Vec3i(signDirection.modX, 0, signDirection.modZ) return isBlockLoaded(world, signLoc.x, signLoc.y, signLoc.z) } @@ -152,18 +150,19 @@ abstract class MultiblockEntity( * Gets the sign of this multiblock **/ fun getSign(): Sign? { - return getSignFromOrigin(world, vec3i, structureDirection).state as? Sign + return getSignFromOrigin(world, globalVec3i, structureDirection).state as? Sign } - fun getSignLocation() = getSignFromOrigin(world, vec3i, structureDirection).location - fun getSignBlock() = getSignFromOrigin(world, vec3i, structureDirection) - fun getSignKey() = getRelative(locationKey, structureDirection.oppositeFace) + fun getSignLocation() = getSignFromOrigin(world, globalVec3i, structureDirection).location + fun getSignBlock() = getSignFromOrigin(world, globalVec3i, structureDirection) + fun getSignKey() = getRelative(globalBlockKey, structureDirection.oppositeFace) /** * Gets the origin block of this multiblock **/ fun getOrigin(): Block { - return world.getBlockAt(x, y, z) + val globalLoc = globalVec3i + return world.getBlockAt(globalLoc.x, globalLoc.y, globalLoc.z) } /** @@ -171,9 +170,10 @@ abstract class MultiblockEntity( **/ fun isIntact(checkSign: Boolean = true): Boolean { if (checkSign && getSign() == null) return false + val globalLoc = globalVec3i return multiblock.blockMatchesStructure( - world.getBlockAt(x, y, z), + world.getBlockAt(globalLoc.x, globalLoc.y, globalLoc.z), structureDirection, loadChunks = false, particles = false @@ -181,14 +181,6 @@ abstract class MultiblockEntity( } fun displace(movement: StarshipMovement) { - val newX = movement.displaceX(x, z) - val newY = movement.displaceY(y) - val newZ = movement.displaceZ(z, x) - - this.x = newX - this.y = newY - this.z = newZ - val world = movement.newWorld if (world != null) { this.world = world @@ -204,17 +196,17 @@ abstract class MultiblockEntity( * **/ fun getBlockRelative(right: Int, up: Int, forward: Int): Block { - val (x, y, z) = getRelative(vec3i, structureDirection, right = right, up = up, forward = forward) + val (x, y, z) = getRelative(globalVec3i, structureDirection, right = right, up = up, forward = forward) return world.getBlockAt(x, y, z) } fun getPosRelative(right: Int, up: Int, forward: Int): Vec3i { - return getRelative(vec3i, structureDirection, right = right, up = up, forward = forward) + return getRelative(globalVec3i, structureDirection, right = right, up = up, forward = forward) } fun getKeyRelative(right: Int, up: Int, forward: Int): BlockKey { - return toBlockKey(getRelative(vec3i, structureDirection, right = right, up = up, forward = forward)) + return toBlockKey(getRelative(globalVec3i, structureDirection, right = right, up = up, forward = forward)) } fun getInventory(right: Int, up: Int, forward: Int): Inventory? { @@ -334,26 +326,15 @@ abstract class MultiblockEntity( // Util protected fun none(): InputsData = InputsData.builder(this).build() - val linkages = mutableMapOf() - - protected fun registerLinkage(right: Int, up: Int, forward: Int, linkageDirection: RelativeFace, allowedEntities: Array>): Supplier { - val realLocKey = toBlockKey(getPosRelative(right, up, forward)) - val new = MultiblockLinkage(this, allowedEntities, realLocKey, linkageDirection[structureDirection]) - - val id = UUID.randomUUID() + val linkages = mutableListOf() - linkages[id] = (realLocKey) - manager.getLinkageManager().registerLinkage(realLocKey, new) - - return Supplier { - val currentPos = linkages[id] ?: return@Supplier null - val linkage = manager.getLinkageManager().getLinkages(currentPos).firstOrNull() { it.owner == this } - linkage?.getOtherEnd(manager.getLinkageManager()) - } + fun reRegisterLinkages() { + removeLinkages() + linkages.forEach { t -> t.register() } } - private fun removeLinkages() { - for (blockKey in linkages.values) manager.getLinkageManager().deRegisterLinkage(blockKey) + fun removeLinkages() { + linkages.forEach { linkage -> linkage.deRegister() } } override fun handlerGetWorld(): World { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt index 728e831582..a9ac8772b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkage.kt @@ -16,7 +16,6 @@ open class MultiblockLinkage( fun getLinkLocation(): BlockKey = getRelative(location, linkDirection) fun displace(movement: StarshipMovement) { - location = movement.displaceKey(location) linkDirection = movement.displaceFace(linkDirection) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt index 49d225e749..e7ec3cb7e0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/MultiblockLinkages.kt @@ -21,21 +21,4 @@ abstract class MultiblockLinkageManager { fun getLinkages(location: BlockKey): Set { return linkages[location]?.getLinkages() ?: setOf() } - - fun transferTo(other: MultiblockLinkageManager) { - for ((key, holder) in linkages) { - val linkages = holder.getLinkages() - for (linkage in linkages) other.registerLinkage(key, linkage) - } - } - - fun transferTo(keys: Iterable, other: MultiblockLinkageManager) { - val intersect = linkages.keys.intersect(keys.toSet()) - - for (key in intersect) { - val holder = linkages[key] ?: continue - val linkages = holder.getLinkages() - for (linkage in linkages) other.registerLinkage(key, linkage) - } - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt index 5bdf0ad114..9816f15f55 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/linkages/ShipLinkageManager.kt @@ -1,37 +1,16 @@ package net.horizonsend.ion.server.features.multiblock.entity.linkages -import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.manager.ShipMultiblockManager import net.horizonsend.ion.server.features.starship.movement.StarshipMovement -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyZ -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import java.util.concurrent.ConcurrentHashMap class ShipLinkageManager(private val shipMultiblockManager: ShipMultiblockManager) : MultiblockLinkageManager() { - fun pilot() { - val old = shipMultiblockManager.world.ion.multiblockManager.linkageManager - val newKeys = shipMultiblockManager.starship.blocks.mapTo(LongOpenHashSet()) { toBlockKey(blockKeyX(it), blockKeyY(it), blockKeyZ(it)) } - old.transferTo(newKeys, this) - } - - fun release() { - transferTo(shipMultiblockManager.world.ion.multiblockManager.linkageManager) - } - override var linkages: ConcurrentHashMap = ConcurrentHashMap() fun displace(movement: StarshipMovement) { - val new: ConcurrentHashMap = ConcurrentHashMap() - - for ((key, holder) in linkages) { + for ((_, holder) in linkages) { holder.displace(movement) - new[movement.displaceKey(key)] = holder } - - linkages = new } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt index d05cea1c2e..cf2d2d156d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/BasicFluidStoringEntity.kt @@ -25,7 +25,7 @@ abstract class BasicFluidStoringEntity( world: World, structureDirection: BlockFace, storage: InternalStorage -) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), FluidStoringEntity { +) : MultiblockEntity(manager, multiblock, world, x, y, z, structureDirection), FluidStoringEntity { @Suppress("LeakingThis") override val fluidStores: Array = arrayOf( loadStoredResource(data, "main", Component.text("Main Storage"), NamespacedKeys.MAIN_STORAGE, storage) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt index 659f1ff556..6d2e3205d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/fluids/FluidStoringEntity.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.multiblock.entity.type.fluids -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.InternalStorage import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.storage.StorageContainer @@ -8,7 +7,6 @@ import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.STORAGES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.kyori.adventure.text.Component import org.bukkit.NamespacedKey import org.bukkit.persistence.PersistentDataAdapterContext @@ -144,15 +142,4 @@ interface FluidStoringEntity { } val fluidInputOffset: Vec3i - - fun getFluidInputLocation(): Vec3i { - this as MultiblockEntity - return getRelative( - origin = vec3i, - forwardFace= structureDirection, - right = fluidInputOffset.x, - up = fluidInputOffset.y, - forward = fluidInputOffset.z - ) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt index c4db573d3a..374c4209b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/type/power/SimplePoweredEntity.kt @@ -25,7 +25,7 @@ abstract class SimplePoweredEntity( world: World, structureDirection: BlockFace, final override val maxPower: Int -) : MultiblockEntity(manager, multiblock, x, y, z, world, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { +) : MultiblockEntity(manager, multiblock, world, x, y, z, structureDirection), PoweredMultiblockEntity, DisplayMultiblockEntity { @Suppress("LeakingThis") // Only a reference is needed, max power is provided in the constructor final override val powerStorage: PowerStorage = PowerStorage( this, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt new file mode 100644 index 0000000000..67442e7190 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt @@ -0,0 +1,75 @@ +package net.horizonsend.ion.server.features.multiblock.linkage + +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkage +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import java.util.function.Supplier +import kotlin.reflect.KClass + +class MultiblockLinkageHolder( + val entity: MultiblockEntity, + val offsetRight: Int, + val offsetUp: Int, + val offsetForward: Int, + val allowedEntities: Array>, + val linkageDirection: RelativeFace +) : Supplier { + var location: BlockKey = toBlockKey(entity.getPosRelative(offsetRight, offsetUp, offsetForward)) + + fun register() { + location = toBlockKey(entity.getPosRelative(offsetRight, offsetUp, offsetForward)) + + val manager = entity.manager + + val new = MultiblockLinkage( + entity, + allowedEntities, + location, + linkageDirection[entity.structureDirection] + ) + + manager.getLinkageManager().registerLinkage(location, new) + } + + fun deRegister() { + val manager = entity.manager + + manager.getLinkageManager().deRegisterLinkage(location) + } + + override fun get(): MultiblockEntity? { + val manager = entity.manager + val linkage = manager + .getLinkageManager() + .getLinkages(location) + .firstOrNull { it.owner == this } + + return linkage?.getOtherEnd(manager.getLinkageManager()) + } + + companion object { + fun MultiblockEntity.createLinkage( + offsetRight: Int, + offsetUp: Int, + offsetForward: Int, + linkageDirection: RelativeFace, + allowedEntities: Array> + ): MultiblockLinkageHolder { + val holder = MultiblockLinkageHolder( + this, + offsetRight, + offsetUp, + offsetForward, + allowedEntities, + linkageDirection + ) + + linkages.add(holder) + + holder.register() + return holder + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 1e498fbf0b..533409988a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -11,7 +11,11 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isWallSign @@ -52,25 +56,25 @@ abstract class MultiblockManager(val log: Logger) { **/ fun addMultiblockEntity(entity: MultiblockEntity, save: Boolean = true, ensureSign: Boolean = false) { if (ensureSign) { - val signOrigin = MultiblockEntity.getSignFromOrigin(entity.world, entity.vec3i, entity.structureDirection) + val signOrigin = MultiblockEntity.getSignFromOrigin(entity.world, entity.globalVec3i, entity.structureDirection) if (!signOrigin.type.isWallSign) { - log.info("Removing invalid multiblock entity at ${entity.vec3i} on ${entity.world.name}") + log.info("Removing invalid multiblock entity at ${entity.globalVec3i} on ${entity.world.name}") entity.remove() return } } - multiblockEntities.remove(entity.locationKey)?.processRemoval() - multiblockEntities[entity.locationKey] = entity + multiblockEntities.remove(entity.localBlockKey)?.processRemoval() + multiblockEntities[entity.localBlockKey] = entity entity.processLoad() if (entity is SyncTickingMultiblockEntity) { - syncTickingMultiblockEntities[entity.locationKey] = entity + syncTickingMultiblockEntities[entity.localBlockKey] = entity } if (entity is AsyncTickingMultiblockEntity) { - asyncTickingMultiblockEntities[entity.locationKey] = entity + asyncTickingMultiblockEntities[entity.localBlockKey] = entity } if (save) save() @@ -148,24 +152,42 @@ abstract class MultiblockManager(val log: Logger) { fun isOccupied(x: Int, y: Int, z: Int): Boolean = multiblockEntities.containsKey(toBlockKey(x, y, z)) - fun handleTransfer(location: BlockKey, destination: MultiblockManager) { - val atLocation = get(location) ?: return + fun handleTransferTo(oldBlockKey: BlockKey, newBlockKey: BlockKey, destination: MultiblockManager) { + val atLocation = get(oldBlockKey) ?: return + + // Remove all ties to old manager and other multis atLocation.releaseInputs() - atLocation.manager = this - multiblockEntities.remove(location) + atLocation.removeLinkages() + + // Transfer manager + atLocation.manager = destination + + // Remove current occupant at spot to handle it properly + multiblockEntities.remove(oldBlockKey) - destination.multiblockEntities[location] = atLocation + destination.multiblockEntities[newBlockKey] = atLocation + if (oldBlockKey != newBlockKey) { + atLocation.localOffsetX = getX(newBlockKey) + atLocation.localOffsetY = getY(newBlockKey) + atLocation.localOffsetZ = getZ(newBlockKey) + } + + // Tie into new network atLocation.registerInputs() + atLocation.linkages.forEach { t -> t.register() } if (atLocation is SyncTickingMultiblockEntity) { - destination.syncTickingMultiblockEntities[location] = atLocation - syncTickingMultiblockEntities.remove(location) + destination.syncTickingMultiblockEntities[newBlockKey] = atLocation + syncTickingMultiblockEntities.remove(oldBlockKey) } if (atLocation is AsyncTickingMultiblockEntity) { - destination.asyncTickingMultiblockEntities[location] = atLocation - asyncTickingMultiblockEntities.remove(location) + destination.asyncTickingMultiblockEntities[newBlockKey] = atLocation + asyncTickingMultiblockEntities.remove(oldBlockKey) } } + + open fun getGlobalCoordinate(localVec3i: Vec3i): Vec3i = localVec3i + open fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i = globalVec3i } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index ffcd35ea05..92c6c92546 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -19,18 +19,18 @@ import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import java.util.concurrent.ConcurrentHashMap class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServer.slF4JLogger) { + var referenceForward: BlockFace = BlockFace.NORTH + private val multiblockLinkageManager = ShipLinkageManager(this) override var multiblockEntities: ConcurrentHashMap = ConcurrentHashMap() @@ -56,21 +56,32 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe return type.get(starship) } - init { + fun processLoad(): ShipMultiblockManager { loadEntities() tryFixEntities() - multiblockLinkageManager.pilot() + multiblockLinkageManager + MultiblockTicking.registerMultiblockManager(this) + + return this } private fun loadEntities() { val worldManager = world.ion.multiblockManager starship.iterateBlocks { x, y, z -> - val modernBlockKey = toBlockKey(x, y, z) - val manager = worldManager.getChunkManager(modernBlockKey) ?: return@iterateBlocks - - manager.handleTransfer(modernBlockKey, this) + val globalKey = toBlockKey(x, y, z) + val manager = worldManager.getChunkManager(globalKey) ?: return@iterateBlocks + + manager.handleTransferTo( + globalKey, + toBlockKey( + x - starship.centerOfMass.x, + y - starship.centerOfMass.y, + z - starship.centerOfMass.z, + ), + this + ) } } @@ -82,84 +93,30 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe private fun releaseEntities() { val worldManager = world.ion.multiblockManager - for ((key, multiblockEntity) in multiblockEntities) { - val network = worldManager.getChunkManager(key) ?: continue + for ((localKey, multiblockEntity) in multiblockEntities) { + val network = worldManager.getChunkManager(multiblockEntity.globalBlockKey) ?: continue // If it was lost, don't place it back if (!multiblockEntity.isIntact(checkSign = true)) { + println("Not intact") multiblockEntity.processRemoval() continue } - network.getAllMultiblockEntities()[key] = multiblockEntity - multiblockEntity.manager = network - } - - for ((key, multiblockEntity) in syncTickingMultiblockEntities) { - val network = worldManager.getChunkManager(key) ?: continue - - // If it was lost, don't place it back - if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { - multiblockEntity.processRemoval() - continue - } - - network.syncTickingMultiblockEntities[key] = multiblockEntity - } - - for ((key, multiblockEntity) in asyncTickingMultiblockEntities) { - val network = worldManager.getChunkManager(key) ?: continue - - // If it was lost, don't place it back - if (!(multiblockEntity as MultiblockEntity).isIntact(checkSign = true)) { - multiblockEntity.processRemoval() - continue - } - - network.asyncTickingMultiblockEntities[key] = multiblockEntity + handleTransferTo( + localKey, + multiblockEntity.globalBlockKey, + network + ) } } - private fun displaceKey(movement: StarshipMovement, key: BlockKey): BlockKey { - val x = getX(key) - val y = getY(key) - val z = getZ(key) - - return toBlockKey( - movement.displaceX(x, z), - movement.displaceY(y), - movement.displaceZ(z, x), - ) - } - fun displace(movement: StarshipMovement) { - val newEntities = ConcurrentHashMap() - for (entry in multiblockEntities) { val entity = entry.value entity.displace(movement) - - newEntities[displaceKey(movement, entry.key)] = entity } - multiblockEntities = newEntities - - val newSyncTicking = ConcurrentHashMap() - - for (entry in syncTickingMultiblockEntities) { - newSyncTicking[displaceKey(movement, entry.key)] = entry.value - } - - syncTickingMultiblockEntities = newSyncTicking - - val newAsyncTicking = ConcurrentHashMap() - - for (entry in asyncTickingMultiblockEntities) { - newAsyncTicking[displaceKey(movement, entry.key)] = entry.value - } - - asyncTickingMultiblockEntities = newAsyncTicking - multiblockLinkageManager.displace(movement) } @@ -172,18 +129,21 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe val state = world.getBlockState(x, y, z) as? Sign ?: return@iterateBlocks val origin = MultiblockEntity.getOriginFromSign(state) - if (isOccupied(origin.x, origin.y, origin.z)) return@iterateBlocks + if (isOccupied( + origin.x - starship.centerOfMass.x, + origin.y - starship.centerOfMass.y, + origin.z - starship.centerOfMass.z + )) return@iterateBlocks val multiblock = MultiblockAccess.getFast(state) if (multiblock !is EntityMultiblock<*>) return@iterateBlocks val data = state.persistentDataContainer.get(NamespacedKeys.MULTIBLOCK_ENTITY_DATA, PersistentMultiblockData) ?: return MultiblockEntities.migrateFromSign(state, multiblock) - // In case it moved - data.x = origin.x - data.y = origin.y - data.z = origin.z + data.x = origin.x - starship.centerOfMass.x + data.y = origin.y - starship.centerOfMass.y + data.z = origin.z - starship.centerOfMass.z data.signOffset = state.getFacing().oppositeFace val new = MultiblockEntities.loadFromData(multiblock, this, data) @@ -192,4 +152,12 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe addMultiblockEntity(new) } } + + override fun getGlobalCoordinate(localVec3i: Vec3i): Vec3i { + return starship.getGlobalCoordinate(localVec3i) + } + + override fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i { + return starship.getLocalCoordinate(globalVec3i) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt index 702b3c72a8..f4f323bf35 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/WorldMultiblockManager.kt @@ -56,6 +56,9 @@ class WorldMultiblockManager(val world: IonWorld) { return chunk.multiblockManager[key] } + /** + * Gets the multiblock manager of the chunk at the provided key, if one is loaded + **/ fun getChunkManager(key: BlockKey): ChunkMultiblockManager? { return world.getChunk(getX(key).shr(4), getZ(key).shr(4))?.multiblockManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt index eac8f6bdab..a408c22c7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/drills/DrillMultiblock.kt @@ -156,7 +156,7 @@ abstract class DrillMultiblock(val tierText: String, val tierMaterial: Material) val power = powerStorage.getPower() if (power == 0) { disable() - return player.alertSubtitle("Your drill at $vec3i ran out of power! It was disabled.") + return player.alertSubtitle("Your drill at $globalVec3i ran out of power! It was disabled.") } val inSpace = world.ion.hasFlag(WorldFlag.SPACE_WORLD) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt index 9ee9d94b61..d69f19e6c8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt @@ -59,7 +59,7 @@ object CanisterVentMultiblock : Multiblock(), EntityMultiblock = arrayOf( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt index a43417ab06..8322bf00f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ItemSplitterMultiblock.kt @@ -129,7 +129,7 @@ object ItemSplitterMultiblock : Multiblock(), InteractableMultiblock, EntityMult world: World, structureDirection: BlockFace, private var isBlacklist: Boolean - ) : MultiblockEntity(manager, ItemSplitterMultiblock, x, y, z, world, structureDirection), SyncTickingMultiblockEntity, LegacyMultiblockEntity { + ) : MultiblockEntity(manager, ItemSplitterMultiblock, world, x, y, z, structureDirection), SyncTickingMultiblockEntity, LegacyMultiblockEntity { override val tickingManager: TickingManager = TickingManager(interval = 20) override val inputsData: InputsData = none() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index b3376a50a0..8ce7388a15 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -78,9 +78,12 @@ object MobDefender : Multiblock(), EntityMultiblock 0.0 + RelativeFace.RIGHT -> 90.0 + RelativeFace.LEFT -> -90.0 + RelativeFace.BACKWARD -> 180.0 + else -> throw IllegalArgumentException("Illegal forward face: $to") + } + + val cosTheta: Double = cos(Math.toRadians(rotation)) + val sinTheta: Double = sin(Math.toRadians(rotation)) + + return Vec3i( + (vec3i.x.toDouble() * cosTheta - vec3i.z.toDouble() * sinTheta).roundToInt(), + vec3i.y, + (vec3i.x.toDouble() * sinTheta + vec3i.z.toDouble() * cosTheta).roundToInt() + ) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt index 986493e644..a03b04107c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/active/ActiveStarshipFactory.kt @@ -35,6 +35,7 @@ object ActiveStarshipFactory { val starship = createStarship(data, blocks, carriedShips) + starship.multiblockManager.processLoad() initSubsystems(feedbackDestination, starship) return starship @@ -113,6 +114,8 @@ object ActiveStarshipFactory { .maxByOrNull { it.value.maxSpeed } ?.key ?: starship.forward + + starship.multiblockManager.referenceForward = starship.forward } private fun prepareShields(starship: ActiveControlledStarship) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt index 74e984ca19..2cd4b5ae17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/subsystem/misc/MiningLaserSubsystem.kt @@ -39,7 +39,7 @@ import org.bukkit.util.Vector class MiningLaserSubsystem( override val starship: ActiveControlledStarship, override val entity: MiningLaserMultiblock.MiningLaserMultiblockEntity, -) : WeaponSubsystem(starship, entity.vec3i), ManualWeaponSubsystem, DirectionalSubsystem, MultiblockEntitySubsystem { +) : WeaponSubsystem(starship, entity.globalVec3i), ManualWeaponSubsystem, DirectionalSubsystem, MultiblockEntitySubsystem { val multiblock = entity.multiblock override var face: BlockFace = entity.structureDirection diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 3d810a9ab0..326a8ff10d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -26,7 +26,7 @@ import java.util.concurrent.Executors import kotlin.concurrent.fixedRateTimer object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick to wait on the full server startup. */) { - private val transportManagers = ConcurrentHashMap.newKeySet() + private val transportManagers = ConcurrentHashMap.newKeySet>() lateinit var monitorThread: Timer lateinit var executor: ExecutorService @@ -54,11 +54,11 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t if (::executor.isInitialized) executor.shutdown() } - fun registerTransportManager(manager: TransportManager) { + fun registerTransportManager(manager: TransportManager<*>) { transportManagers.add(manager) } - fun removeTransportManager(manager: TransportManager) { + fun removeTransportManager(manager: TransportManager<*>) { transportManagers.remove(manager) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index b8557e8a95..f52155a509 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -12,9 +12,8 @@ import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.Block -import org.bukkit.block.data.BlockData -class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { +class ChunkTransportManager(val chunk: IonChunk) : TransportManager>() { override val extractorManager: ChunkExtractorManager = ChunkExtractorManager(this) override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } @@ -22,6 +21,13 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { override val itemPipeManager = ChunkCacheHolder(this) { ItemTransportCache(it) } // override val fluidNodeManager = ChunkCacheHolder(this) { FluidTransportCache(it) } + override val networks: Array> = arrayOf( + powerNodeManager, + solarPanelManager, + itemPipeManager, +// fluidNodeManager + ) + override fun getInputProvider(): InputManager { return chunk.world.ion.inputManager } @@ -31,16 +37,12 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { } fun setup() { - powerNodeManager.handleLoad() - solarPanelManager.handleLoad() -// fluidNodeManager.handleLoad() + networks.forEach { it.handleLoad() } NewTransport.registerTransportManager(this) } fun onUnload() { - powerNodeManager.handleUnload() - solarPanelManager.handleUnload() -// fluidNodeManager.handleUnload() + networks.forEach { it.handleUnload() } NewTransport.removeTransportManager(this) } @@ -49,36 +51,14 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager() { } fun invalidateCache(key: BlockKey) { - powerNodeManager.cache.invalidate(key) - solarPanelManager.cache.invalidate(key) -// fluidNodeManager.cache.invalidate(key) + networks.forEach { it.cache.invalidate(key) } } fun processBlockRemoval(key: BlockKey) { - powerNodeManager.cache.invalidate(key) - solarPanelManager.cache.invalidate(key) -// fluidNodeManager.cache.invalidate(key) -// pipeGrid.processBlockRemoval(key) + networks.forEach { it.cache.invalidate(key) } } fun processBlockChange(block: Block) { - powerNodeManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) - solarPanelManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) -// fluidNodeManager.cache.invalidate(toBlockKey(block.x, block.y, block.z)) -// pipeGrid.processBlockAddition(key, new) - } - - fun processBlockChange(position: BlockKey, data: BlockData) { - powerNodeManager.cache.invalidate(position) - solarPanelManager.cache.invalidate(position) -// fluidNodeManager.cache.invalidate(position) -// pipeGrid.processBlockAddition(key, new) - } - - fun refreshBlock(position: BlockKey) { - powerNodeManager.cache.invalidate(position) - solarPanelManager.cache.invalidate(position) -// fluidNodeManager.cache.invalidate(position) -// pipeGrid.processBlockAddition(key, new) + networks.forEach { it.cache.invalidate(toBlockKey(block.x, block.y, block.z)) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 57836e133f..9cf9dc1657 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -10,9 +10,10 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportC import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.nodes.inputs.ShipInputManager +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -class ShipTransportManager(val starship: Starship) : TransportManager() { - override val extractorManager: ShipExtractorManager = ShipExtractorManager(starship) +class ShipTransportManager(val starship: Starship) : TransportManager>() { + override val extractorManager: ShipExtractorManager = ShipExtractorManager(this) val inputManager = ShipInputManager(this) override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } @@ -20,34 +21,42 @@ class ShipTransportManager(val starship: Starship) : TransportManager() { override val itemPipeManager = ShipCacheHolder(this) { ItemTransportCache(it) } // override val fluidNodeManager = ShipCacheHolder(this) { FluidTransportCache(it) } + override val networks: Array> = arrayOf( + powerNodeManager, + solarPanelManager, + itemPipeManager, +// fluidNodeManager + ) + init { load() } fun load() { - powerNodeManager.capture() - solarPanelManager.capture() -// fluidNodeManager.capture() + networks.forEach { it.handleLoad() } extractorManager.loadExtractors() NewTransport.registerTransportManager(this) } fun release() { - powerNodeManager.release() - solarPanelManager.release() -// fluidNodeManager.release() - extractorManager.releaseExtractors() + networks.forEach { it.release() } NewTransport.removeTransportManager(this) + extractorManager.releaseExtractors() } fun displace(movement: StarshipMovement) { - powerNodeManager.displace(movement) - solarPanelManager.displace(movement) -// fluidNodeManager.displace(movement) - extractorManager.displace(movement) + networks.forEach { it.displace(movement) } } override fun getInputProvider(): InputManager { return inputManager } + + override fun getGlobalCoordinate(localVec3i: Vec3i): Vec3i { + return starship.getGlobalCoordinate(localVec3i) + } + + override fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i { + return starship.getLocalCoordinate(globalVec3i) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index e3adc45858..71b4c08281 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -6,14 +6,18 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCa import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i -abstract class TransportManager { +abstract class TransportManager> { abstract val extractorManager: ExtractorManager + abstract val powerNodeManager: CacheHolder abstract val solarPanelManager: CacheHolder abstract val itemPipeManager: CacheHolder // abstract val fluidNodeManager: CacheHolder + abstract val networks: Array + abstract fun getInputProvider(): InputManager fun tick() { @@ -23,4 +27,7 @@ abstract class TransportManager { // fluidNodeManager.cache.tickExtractor(extractor.pos, delta) } } + + open fun getGlobalCoordinate(localVec3i: Vec3i): Vec3i = localVec3i + open fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i = globalVec3i } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index 46533dbb51..de460c662d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -1,18 +1,19 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap -import net.horizonsend.ion.server.features.starship.Starship -import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.chunkKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe -class ShipExtractorManager(val starship: Starship) : ExtractorManager() { +class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager() { var extractors = Long2ObjectOpenHashMap() override fun getExtractors(): Collection { @@ -25,9 +26,12 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { /** Returns true if an extractor was registered */ override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - if (ensureExtractor && getBlockTypeSafe(starship.world, x, y, z) != EXTRACTOR_TYPE) return false - val key = toBlockKey(x, y, z) + if (ensureExtractor && getBlockTypeSafe(manager.starship.world, x, y, z) != EXTRACTOR_TYPE) return false + + // Store extractors via local coordinates + val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) extractors[key] = ExtractorData(key) + return true } @@ -40,8 +44,11 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { } fun loadExtractors() { - starship.iterateBlocks { x, y, z -> - if (registerExtractor(x, y, z, true)) NewTransport.removeExtractor(starship.world, x, y, z) + manager.starship.iterateBlocks { x, y, z -> + // If an extractor is added at the starship, remove the one in the world + if (registerExtractor( x, y, z, true)) { + NewTransport.removeExtractor(manager.starship.world, x, y, z) + } } } @@ -49,22 +56,16 @@ class ShipExtractorManager(val starship: Starship) : ExtractorManager() { // We can disregard the extractor data // Its more so a convenience thing val byChunk = extractors.keys.groupBy { key -> - chunkKey(getX(key).shr(4), getZ(key).shr(4)) + chunkKey((getX(key) + manager.starship.centerOfMass.x).shr(4), (getZ(key) + manager.starship.centerOfMass.z).shr(4)) } for ((chunkKey, entries) in byChunk) { - val ionChunk = IonChunk[starship.world, chunkKey] ?: continue + val ionChunk = IonChunk[manager.starship.world, chunkKey] ?: continue for (entry in entries) { - ionChunk.transportNetwork.extractorManager.registerExtractor(entry, ensureExtractor = true) + val worldCoord = toBlockKey(manager.getGlobalCoordinate(toVec3i(entry))) + ionChunk.transportNetwork.extractorManager.registerExtractor(worldCoord, ensureExtractor = true) } } } - - fun displace(movement: StarshipMovement) { - val new = Long2ObjectOpenHashMap() - extractors.forEach { new[movement.displaceKey(it.key)] = it.value } - - extractors = new - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt index 21996ed532..1760f46e19 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World interface CacheHolder { - val transportManager: TransportManager + val transportManager: TransportManager<*> val cache: T fun getWorld(): World diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt index 84d9b8c0f3..05ec9ca94e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt @@ -36,6 +36,7 @@ class ChunkCacheHolder private constructor (override val tran val xDiff = transportManager.chunk.x - chunkX val zDiff = transportManager.chunk.z - chunkZ + // Only allow access to adjacent chunks if (xDiff > 1 || xDiff < -1) return null if (zDiff > 1 || zDiff < -1) return null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 615c9e2c36..6c84436b40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -10,7 +10,9 @@ import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import org.bukkit.World import kotlin.properties.Delegates @@ -26,7 +28,12 @@ class ShipCacheHolder(override val transportManager: ShipTran override fun handleLoad() { transportManager.starship.iterateBlocks { x, y, z -> IonChunk[transportManager.starship.world, x, z]?.let { cache.type.get(it).invalidate(x, y, z) } - cache.cache(toBlockKey(x, y, z)) + + val local = transportManager.getLocalCoordinate(Vec3i(x, y, z)) + val block = getBlockIfLoaded(transportManager.starship.world, x, y, z) ?: return + + // Cache at local coordinate + cache.cache(toBlockKey(local), block) } } @@ -47,14 +54,6 @@ class ShipCacheHolder(override val transportManager: ShipTran return transportManager.extractorManager } - fun capture() { - transportManager.starship.iterateBlocks { x, y, z -> - NewTransport.invalidateCache(getWorld(), x, y, z) - - cache.cache(toBlockKey(x, y, z)) - } - } - fun displace(movement: StarshipMovement) { cache.displace(movement) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 6835355f66..e470ba6e13 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -84,16 +84,13 @@ abstract class TransportCache(val holder: CacheHolder<*>) { fun getRawCache() = cache fun displace(movement: StarshipMovement) { - val new = ConcurrentHashMap() + for (state in getRawCache().values) { + if (state !is CacheState.Present) continue + val node = state.node + if (node !is ComplexNode) continue - for ((key, cached) in cache) { - val newKey = movement.displaceKey(key) - val presentNode = (cached as? CacheState.Present)?.node - if (presentNode is ComplexNode) presentNode.displace(movement) - new[newKey] = cached + node.displace(movement) } - - cache = new } /** From 58aa057bc5fd40792719bb9e407e631c443440b2 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:15:55 -0600 Subject: [PATCH 413/500] Working power transfer on ships --- .../command/misc/TransportDebugCommand.kt | 8 +++---- .../linkage/MultiblockLinkageHolder.kt | 11 +++++++++- .../multiblock/manager/MultiblockManager.kt | 4 ++++ .../manager/ShipMultiblockManager.kt | 6 ++++- .../transport/manager/holders/CacheHolder.kt | 5 ++++- .../manager/holders/ChunkCacheHolder.kt | 5 +++++ .../manager/holders/ShipCacheHolder.kt | 8 ++++++- .../nodes/cache/FluidTransportCache.kt | 4 ++-- .../nodes/cache/ItemTransportCache.kt | 2 +- .../nodes/cache/PowerTransportCache.kt | 18 ++++++++++----- .../transport/nodes/cache/SolarPanelCache.kt | 16 ++++++-------- .../transport/nodes/cache/TransportCache.kt | 22 ++++++++++--------- .../transport/nodes/inputs/InputsData.kt | 14 +++++++++++- .../transport/nodes/types/PowerNode.kt | 4 ---- 14 files changed, 86 insertions(+), 41 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 0539e3e6a8..06f469b263 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -94,10 +94,10 @@ object TransportDebugCommand : SLCommand() { fun dumpInputsShip(sender: Player, type: CacheType) { val ship = getStarshipRiding(sender) val inputManager = ship.transportManager.inputManager - val loc = Vec3i(sender.location) - val inputs = inputManager.getLocations(type) - .map { toVec3i(it) } - .filter { it.distance(loc) < 100.0 } + + val inputs = inputManager + .getLocations(type) + .map { ship.transportManager.getGlobalCoordinate(toVec3i(it)) } sender.highlightBlocks(inputs, 50L) sender.information("${inputs.size} inputs") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt index 67442e7190..3e1ff0e0a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/linkage/MultiblockLinkageHolder.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkage import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import java.util.function.Supplier import kotlin.reflect.KClass @@ -19,7 +20,15 @@ class MultiblockLinkageHolder( var location: BlockKey = toBlockKey(entity.getPosRelative(offsetRight, offsetUp, offsetForward)) fun register() { - location = toBlockKey(entity.getPosRelative(offsetRight, offsetUp, offsetForward)) + val newPos = getRelative( + origin = entity.localVec3i, + forwardFace = entity.structureDirection, + right = offsetRight, + up = offsetUp, + forward = offsetForward + ) + + location = toBlockKey(newPos) val manager = entity.manager diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 533409988a..03e216830e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.multiblock.manager import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkageManager @@ -189,5 +190,8 @@ abstract class MultiblockManager(val log: Logger) { open fun getGlobalCoordinate(localVec3i: Vec3i): Vec3i = localVec3i open fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i = globalVec3i + + open fun getGlobalMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? = + MultiblockEntities.getMultiblockEntity(world, x, y, z) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 92c6c92546..8a17d2066f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -24,6 +24,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.isWallSign +import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import java.util.concurrent.ConcurrentHashMap @@ -98,7 +99,6 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe // If it was lost, don't place it back if (!multiblockEntity.isIntact(checkSign = true)) { - println("Not intact") multiblockEntity.processRemoval() continue } @@ -160,4 +160,8 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe override fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i { return starship.getLocalCoordinate(globalVec3i) } + + override fun getGlobalMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { + return get(x, y, z) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt index 1760f46e19..4ef4deee2a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -41,5 +42,7 @@ interface CacheHolder { fun getExtractorManager(): ExtractorManager - abstract val nodeProvider: (CacheType, World, BlockKey) -> Node? + fun getInputManager(): InputManager + + val nodeProvider: (CacheType, World, BlockKey) -> Node? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt index 05ec9ca94e..af9c10d3f7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getOrCacheNode @@ -59,4 +60,8 @@ class ChunkCacheHolder private constructor (override val tran override val nodeProvider: (CacheType, World, BlockKey) -> Node? = { cacheType, world, pos -> getOrCacheNode(cacheType, world, pos) } + + override fun getInputManager(): InputManager { + return transportManager.getInputProvider() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 6c84436b40..99a43b88b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.chunk.IonChunk @@ -27,7 +28,7 @@ class ShipCacheHolder(override val transportManager: ShipTran override fun handleLoad() { transportManager.starship.iterateBlocks { x, y, z -> - IonChunk[transportManager.starship.world, x, z]?.let { cache.type.get(it).invalidate(x, y, z) } + IonChunk[transportManager.starship.world, x.shr(4), z.shr(4)]?.let { cache.type.get(it).invalidate(x, y, z) } val local = transportManager.getLocalCoordinate(Vec3i(x, y, z)) val block = getBlockIfLoaded(transportManager.starship.world, x, y, z) ?: return @@ -59,6 +60,7 @@ class ShipCacheHolder(override val transportManager: ShipTran } fun release() { + cache.getRawCache().keys.forEach { key -> cache.getCached(key)?.onInvalidate() } transportManager.starship.iterateBlocks { x, y, z -> NewTransport.invalidateCache(getWorld(), x, y, z) } @@ -67,4 +69,8 @@ class ShipCacheHolder(override val transportManager: ShipTran override val nodeProvider: (CacheType, World, BlockKey) -> Node? = { _, _, pos -> getInternalNode(pos) } + + override fun getInputManager(): InputManager { + return transportManager.inputManager + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 79880c57b8..f00077b2d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -49,7 +49,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa if (source.getStoredResources().isEmpty()) return@submit // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> + val destinations: Collection = getNetworkDestinations(location) { node -> world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } } @@ -85,7 +85,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa /** * Executes the transfer from the source node to the lit of destinations. Transports one fluid at a time. **/ - private fun runFluidTransfer(source: Node.NodePositionData, rawDestinations: List, fluid: Fluid, amount: Int): Int { + private fun runFluidTransfer(source: Node.NodePositionData, rawDestinations: Collection, fluid: Fluid, amount: Int): Int { if (rawDestinations.isEmpty()) return amount val filteredDestinations = rawDestinations.filter { destinationLoc -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 817beb233d..3245e49729 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -10,7 +10,7 @@ import org.bukkit.Material import org.bukkit.craftbukkit.block.impl.CraftGrindstone class ItemTransportCache(holder: CacheHolder): TransportCache(holder) { - override val type: CacheType = CacheType.FLUID + override val type: CacheType = CacheType.ITEMS override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index fddcddd862..196bdcd571 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -11,7 +11,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material.CRAFTING_TABLE @@ -50,13 +49,16 @@ class PowerTransportCache(holder: CacheHolder) : TransportC private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.executor.submit { measureOrFallback(TransportDebugCommand.extractorTickTimes) { val world = holder.getWorld() + val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@measureOrFallback //TODO take from all // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = measureOrFallback(TransportDebugCommand.floodFillTimes) { + val destinations: Collection = measureOrFallback(TransportDebugCommand.floodFillTimes) { getNetworkDestinations(location) { node -> - world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + getInputEntities(node.position).any { entity -> + (entity is PoweredMultiblockEntity) && !entity.powerStorage.isFull() + } } } @@ -93,8 +95,12 @@ class PowerTransportCache(holder: CacheHolder) : TransportC if (transportPower == 0) return@measureOrFallback // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: List = getNetworkDestinations(location) { node -> - holder.getWorld().ion.inputManager.getHolders(CacheType.POWER, node.position).any { entity -> entity is PoweredMultiblockEntity && !entity.powerStorage.isFull() } + val destinations: Collection = measureOrFallback(TransportDebugCommand.solarFloodFillTimes) { + getNetworkDestinations(location) { node -> + getInputEntities(node.position).any { entity -> + (entity is PoweredMultiblockEntity) && !entity.powerStorage.isFull() + } + } } if (destinations.isEmpty()) return@measureOrFallback @@ -160,7 +166,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC for ((index, destination) in filteredDestinations.withIndex()) { val shareFactor = shareFactors[index] ?: continue - val inputData = PowerInputNode.getPoweredEntities(source.world, destination) + val inputData = getInputEntities(destination).filterIsInstance() val share = shareFactor / shareFactorSum diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt index 0615f9e6fa..335851c1d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt @@ -4,12 +4,9 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.getOrCacheNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.Material import org.bukkit.World @@ -40,16 +37,17 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol } fun isSolarPanel(extractorKey: BlockKey): Boolean { - if (getOrCacheNode(CacheType.SOLAR_PANELS, holder.getWorld(), extractorKey) !is SolarPanelComponent.CraftingTable) return false - if (getOrCacheNode(CacheType.SOLAR_PANELS, holder.getWorld(), getRelative(extractorKey, BlockFace.UP, 1)) !is SolarPanelComponent.DiamondBlock) return false - if (getOrCacheNode(CacheType.SOLAR_PANELS, holder.getWorld(), getRelative(extractorKey, BlockFace.UP, 2)) !is SolarPanelComponent.DaylightDetector) return false + if (holder.nodeProvider.invoke(type, holder.getWorld(), extractorKey) !is SolarPanelComponent.CraftingTable) return false + if (holder.nodeProvider.invoke(type, holder.getWorld(), getRelative(extractorKey, BlockFace.UP, 1)) !is SolarPanelComponent.DiamondBlock) return false + if (holder.nodeProvider.invoke(type, holder.getWorld(), getRelative(extractorKey, BlockFace.UP, 2)) !is SolarPanelComponent.DaylightDetector) return false + return true } fun getPower(world: World, extractPos: BlockKey, delta: Double): Int { - val detectorPosition = getRelative(extractPos, BlockFace.UP, 2) + val detectorPosition = holder.transportManager.getGlobalCoordinate(toVec3i(getRelative(extractPos, BlockFace.UP, 2))) val powerMultiplier = if (world.environment == World.Environment.NORMAL) 1.0 else 0.5 - val data = getBlockDataSafe(world, getX(detectorPosition), getY(detectorPosition), getZ(detectorPosition)) as? DaylightDetector ?: return 0 + val data = getBlockDataSafe(world, detectorPosition.x, detectorPosition.y, detectorPosition.z) as? DaylightDetector ?: return 0 val powerRatio = data.power.toDouble() / data.maximumPower.toDouble() val base = ConfigurationFiles.transportSettings().powerConfiguration.solarPanelTickPower * delta diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index e470ba6e13..3616eeabe7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -2,7 +2,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import com.google.common.collect.TreeBasedTable import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder @@ -12,8 +11,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getIdealPath -import net.horizonsend.ion.server.features.transport.util.getOrCacheNode -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -23,6 +20,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isAdjacent import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.set import org.bukkit.block.Block @@ -98,15 +96,18 @@ abstract class TransportCache(val holder: CacheHolder<*>) { * This method is used in conjunction with input registration to allow direct access via signs, and remote access via registered inputs **/ fun getInputEntities(location: BlockKey): Set { - val inputManager = holder.getWorld().ion.inputManager + val inputManager = holder.getInputManager() val registered = inputManager.getHolders(type, location) // The stupid offsets are a list of locations that a multiblock entity would be accessible from if its sign were touching the provided location // Doing a call to try to find a sign is a lot more expensive since it has a getChunk call // // If this actually finds an entity, it makes sure that its sign block is adjacent to the input + val multiblockManager = holder.getMultiblockManager() val adjacentBlocks = stupidOffsets.mapNotNull { - MultiblockEntities.getMultiblockEntity(holder.getWorld(), it.x, it.y, it.z)?.takeIf { entity -> + val loc = Vec3i(it.x, it.y, it.z) + toVec3i(location) + + multiblockManager.getGlobalMultiblockEntity(holder.getWorld(), loc.x, loc.y, loc.z)?.takeIf { entity -> val signLoc = entity.getSignKey() isAdjacent(signLoc, location) } @@ -160,8 +161,8 @@ abstract class TransportCache(val holder: CacheHolder<*>) { inline fun getNetworkDestinations( originPos: BlockKey, check: (Node.NodePositionData) -> Boolean, - ): List { - val originNode = getOrCacheNode(type, holder.getWorld(), originPos) ?: return listOf() + ): Collection { + val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), originPos) ?: return listOf() val visitQueue = ArrayDeque() val visited = LongOpenHashSet() @@ -179,13 +180,14 @@ abstract class TransportCache(val holder: CacheHolder<*>) { val current = visitQueue.removeFirst() visited.add(current.position) - if (current.type is T && check(current)) destinations.add(current.position) - + if (current.type is T && check(current)) { + destinations.add(current.position) + } visitQueue.addAll(current.getNextNodes(holder.nodeProvider, null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) } - return destinations.toList() + return destinations } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt index d3db1db172..d4a138eecf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/inputs/InputsData.kt @@ -2,6 +2,9 @@ package net.horizonsend.ion.server.features.transport.nodes.inputs import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey class InputsData private constructor (val holder: MultiblockEntity, private val inputs: List){ fun registerInputs() { @@ -26,7 +29,16 @@ class InputsData private constructor (val holder: MultiblockEntity, private val private val offsetUp: Int, private val offsetForward: Int, ) { - private fun getRealPos(holder: MultiblockEntity) = holder.getKeyRelative(offsetRight, offsetUp, offsetForward) + private fun getRealPos(holder: MultiblockEntity): BlockKey { + val newPos = getRelative( + origin = holder.localVec3i, + forwardFace = holder.structureDirection, + right = offsetRight, + up = offsetUp, + forward = offsetForward + ) + return toBlockKey(newPos) + } fun register(manager: InputManager, holder: MultiblockEntity) { manager.registerInput(type, getRealPos(holder), holder) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 916533b197..44273d7a0d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -5,12 +5,10 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlerHolder import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.display.FlowMeterDisplayModule -import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -54,7 +52,6 @@ sealed interface PowerNode : Node { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - fun getPoweredEntities(world: World, location: BlockKey) = world.ion.inputManager.getHolders(CacheType.POWER, location).filterIsInstance() } interface MergeNode : PowerNode { @@ -155,7 +152,6 @@ sealed interface PowerNode : Node { override fun handlerGetWorld(): World = world - companion object { private const val NUMBER_STORED_AVERAGES = 20 } } } From 2ecf7ba791c7b493fe2510a7f844230dfa8954a5 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:28:26 -0600 Subject: [PATCH 414/500] Improved rolling average --- .../transport/nodes/types/PowerNode.kt | 42 +++++++------------ .../features/transport/util/RollingAverage.kt | 28 +++++++++++++ 2 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/RollingAverage.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 44273d7a0d..ebf6b06b53 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.RollingAverage import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -19,6 +20,7 @@ import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Axis import org.bukkit.World import org.bukkit.block.BlockFace +import java.text.DecimalFormat sealed interface PowerNode : Node { override val cacheType: CacheType get() = CacheType.POWER @@ -94,43 +96,29 @@ sealed interface PowerNode : Node { } data class PowerFlowMeter(val cache: PowerTransportCache, var face: BlockFace, var world: World, var location: BlockKey) : PowerNode, ComplexNode, DisplayHandlerHolder { - /** Data entry of transferred power, contains the amount and the timestamp if the transfer */ - private data class TransferredPower(val transferred: Int, val time: Long = System.currentTimeMillis()) - - // Use array deque as a stack - private val averages = ArrayDeque(NUMBER_STORED_AVERAGES) + val rollingAverage = RollingAverage() override var isAlive: Boolean = true - - val displayHandler = DisplayHandlers.newBlockOverlay(this, toVec3i(location), face, { FlowMeterDisplayModule(it, this, 0.0, 0.0, 0.0, 0.7f) }) + val displayHandler = DisplayHandlers.newBlockOverlay(this, toVec3i(location), face, { FlowMeterDisplayModule(it, this, 0.0, 0.0, 0.0, 0.7f) }) fun onCompleteChain(transferred: Int) { // Push onto queue - if (averages.size == NUMBER_STORED_AVERAGES) averages.removeFirst() - averages.addLast(TransferredPower(transferred)) - + rollingAverage.addEntry(transferred) displayHandler.update() } - private fun calculateAverage(): Double { - val nonNull = averages.filterNotNull() - val sum = nonNull.sumOf { it.transferred } - - val timeDiff = (System.currentTimeMillis() - nonNull.minOf { it.time }) / 1000.0 - - return sum / timeDiff - } + companion object { + val format = DecimalFormat("##.##") + } fun formatFlow(): Component { - val nonNull = averages.filterNotNull() - var avg = runCatching { calculateAverage().roundToHundredth() }.getOrDefault(0.0) + val avg = runCatching { rollingAverage.getAverage().roundToHundredth() }.getOrDefault(0.0) - // If no averages, or no power has been moved in 5 seconds, go to 0 - if (averages.isEmpty() || System.currentTimeMillis() - nonNull.maxOf { it.time } > 5000) { - avg = 0.0 - } - - return ofChildren(FlowMeterDisplayModule.firstLine, Component.text(avg, NamedTextColor.GREEN), FlowMeterDisplayModule.secondLine) + return ofChildren( + FlowMeterDisplayModule.firstLine, + Component.text(format.format(avg), NamedTextColor.GREEN), + FlowMeterDisplayModule.secondLine + ) } override val pathfindingResistance: Double = 0.5 @@ -151,7 +139,5 @@ sealed interface PowerNode : Node { } override fun handlerGetWorld(): World = world - - companion object { private const val NUMBER_STORED_AVERAGES = 20 } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/RollingAverage.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/RollingAverage.kt new file mode 100644 index 0000000000..586bdb2823 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/RollingAverage.kt @@ -0,0 +1,28 @@ +package net.horizonsend.ion.server.features.transport.util + +class RollingAverage { + /** Data entry of transferred power, contains the amount and the timestamp if the transfer */ + data class TransferredPower(val transferred: Int, val time: Long = System.currentTimeMillis()) + + companion object { private const val NUMBER_STORED_AVERAGES = 20 } + // Use array deque as a stack + private val averages = ArrayDeque(NUMBER_STORED_AVERAGES).apply { + // Initialize with 0 transferred + add(TransferredPower(0, System.currentTimeMillis())) + } + + fun addEntry(amount: Int) { + if (averages.size == NUMBER_STORED_AVERAGES) averages.removeFirst() + averages.addLast(TransferredPower(amount)) + } + + fun getAverage(): Double { + val nonNull = averages.filterNotNull() + val sum = nonNull.sumOf { it.transferred } + + val timeDiff = (System.currentTimeMillis() - nonNull.minOf { it.time }) / 1000.0 + + val rate = sum / timeDiff + return rate + } +} From dd4ccc577fa8be0bfa280539685f54a2f7515330 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:13:41 -0600 Subject: [PATCH 415/500] typo --- .../multiblock/type/autocrafter/AutoCrafterMultiblock.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt index 0e3395f356..3f9af86da1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/autocrafter/AutoCrafterMultiblock.kt @@ -42,7 +42,7 @@ import java.util.Optional private const val POWER_USAGE_PER_INGREDIENT = 15 abstract class AutoCrafterMultiblock( - val tierText: Component, + tierText: Component, private val tierMaterial: Material, private val iterations: Int, ) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { @@ -52,7 +52,7 @@ abstract class AutoCrafterMultiblock( abstract val maxPower: Int - override val displayName: Component = ofChildren(tierText, text("Auto Crafter")) + override val displayName: Component = ofChildren(tierText, text(" Auto Crafter")) override val description: Component get() = text("Executes the recipe outlined in the center dropper. Input items are consumed to craft the output.") override fun MultiblockShape.buildStructure() { From bb832bb7770fbd2e99e022b1d9e1f8c1b72e9085 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 21 Jan 2025 23:59:55 -0600 Subject: [PATCH 416/500] Serialization util --- .../persistence/MetaDataContainer.kt | 39 +++++++++++++++++++ .../persistence/NamespacedKeys.kt | 5 ++- .../persistence/PDCSerializers.kt | 33 ++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt new file mode 100644 index 0000000000..3c20d1b955 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt @@ -0,0 +1,39 @@ +package net.horizonsend.ion.server.miscellaneous.registrations.persistence + +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +data class MetaDataContainer>( + val persistentDataType: C, + val data: V +) { + companion object : PersistentDataType> { + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + override fun getComplexType(): Class> = MetaDataContainer::class.java + + override fun toPrimitive( + complex: MetaDataContainer<*, *>, + context: PersistentDataAdapterContext, + ): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + pdc.set(NamespacedKeys.SERIALIZATION_TYPE, PersistentDataType.STRING, complex.persistentDataType.identifier) + pdc.set(NamespacedKeys.META_DATA, PersistentDataType.TAG_CONTAINER, complex.persistentDataType.serialize(complex.data, context)) + + return pdc + } + + override fun fromPrimitive( + primitive: PersistentDataContainer, + context: PersistentDataAdapterContext, + ): MetaDataContainer<*, *> { + val typeId = primitive.get(NamespacedKeys.SERIALIZATION_TYPE, PersistentDataType.STRING)!! + val type = PDCSerializers[typeId] + + return type.loadMetaDataContainer( + primitive.get(NamespacedKeys.META_DATA, PersistentDataType.TAG_CONTAINER)!!, + context + ) + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 2b860a33d5..d5560d6fa8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -57,7 +57,7 @@ object NamespacedKeys { val SPLITTER_DIRECTION = key("splitter_direction") val USER = key("user") - val USER_NAME = key("user") + val USER_NAME = key("user_name") @Deprecated("") val ORE_CHECK = key("oreCheck") @@ -84,6 +84,9 @@ object NamespacedKeys { val POWER = key("power") val GAS = key("Gas") + val SERIALIZATION_TYPE = key("serialization_type") + val META_DATA = key("meta_data") + val FILTER_DATA = key("filter_data") val FILTER_TYPE = key("filter_type") val FILTER_ENTRY = key("filter_entry") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt new file mode 100644 index 0000000000..dca6e6f20c --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt @@ -0,0 +1,33 @@ +package net.horizonsend.ion.server.miscellaneous.registrations.persistence + +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType +import kotlin.reflect.KClass + +object PDCSerializers { + private val registeredSerializers = mutableMapOf>() + + fun > register(serializer: T): T { + registeredSerializers[serializer.identifier] = serializer + return serializer + } + + operator fun get(identifier: String) : RegisteredSerializer<*> = registeredSerializers[identifier]!! + + abstract class RegisteredSerializer(val identifier: String, val complexType: KClass) : PersistentDataType { + fun serialize(obj: Any, context: PersistentDataAdapterContext): PersistentDataContainer { + require(complexType.isInstance(obj)) + @Suppress("UNCHECKED_CAST") + return toPrimitive(obj as C, context) + } + + fun deserialize(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): C { + return fromPrimitive(primitive, context) + } + + fun loadMetaDataContainer(data: PersistentDataContainer, context: PersistentDataAdapterContext): MetaDataContainer { + return MetaDataContainer(this, deserialize(data, context)) + } + } +} From 02493e29813d2ba61b7c26835c31fb1599bde526 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 12:24:03 -0600 Subject: [PATCH 417/500] start work on new types of extractors --- .../server/command/admin/StructureCreator.kt | 4 +- .../command/misc/TransportDebugCommand.kt | 2 +- .../command/qol/FixExtractorsCommand.kt | 4 +- .../multiblock/shape/MultiblockShape.kt | 4 +- .../factory/StarshipFactoryPrinter.kt | 7 +--- .../server/features/transport/NewTransport.kt | 12 +++--- .../extractors/ChunkExtractorManager.kt | 7 ++-- .../manager/extractors/ExtractorManager.kt | 39 ++++++++++--------- .../extractors/ShipExtractorManager.kt | 5 ++- .../manager/extractors/data/ExtractorData.kt | 20 ++++++++++ .../extractors/data/ItemExtractorData.kt | 6 +++ 11 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt index ec163e3d9c..83f35784cd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/admin/StructureCreator.kt @@ -6,7 +6,7 @@ import co.aikar.commands.annotation.Default import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace @@ -154,7 +154,7 @@ object StructureCreator : SLCommand() { data.material == Material.FLETCHING_TABLE -> ".fluidInput()" data.material == Wires.INPUT_COMPUTER_BLOCK -> ".powerInput()" - data.material == EXTRACTOR_TYPE -> ".extractor()" + data.material == STANDARD_EXTRACTOR_TYPE -> ".extractor()" data.material == Material.HOPPER -> ".hopper()" data.material == Material.DISPENSER -> ".dispenser()" diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 06f469b263..7fba0fb060 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -185,7 +185,7 @@ object TransportDebugCommand : SLCommand() { val (node, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } val grid = type.get(chunk) - if (grid.holder.getExtractorManager().isExtractor(location)) IonChunkCommand.fail { "Extractor not targeted" } + if (grid.holder.getExtractorManager().isExtractorPresent(location)) IonChunkCommand.fail { "Extractor not targeted" } grid.tickExtractor(location, 1.0) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt index 92921e48da..9ddd4ae6fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player @@ -35,7 +35,7 @@ object FixExtractorsCommand : SLCommand() { val block = sender.world.getBlockAt(x, y, z) - if (block.type != EXTRACTOR_TYPE) continue + if (block.type != STANDARD_EXTRACTOR_TYPE) continue if (NewTransport.isExtractor(sender.world, x, y, z)) continue diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt index 6c6aee5c68..dcddf44542 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/shape/MultiblockShape.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ENRICHED_U import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.NETHERITE_CASING import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE import net.horizonsend.ion.server.features.transport.old.Wires import net.horizonsend.ion.server.features.transport.old.pipe.Pipes import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES @@ -481,7 +481,7 @@ class MultiblockShape { fun fluidInput() = type(Material.FLETCHING_TABLE) fun powerInput() = type(Wires.INPUT_COMPUTER_BLOCK) - fun extractor() = type(EXTRACTOR_TYPE) + fun extractor() = type(STANDARD_EXTRACTOR_TYPE) fun sponge() = anyType(Material.SPONGE, Material.WET_SPONGE, alias = "sponge") fun endRod(edit: BlockRequirement.() -> Unit = {}) = type(Material.END_ROD, edit) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt index 9eb24475bc..c9fa535cc2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.factory import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY @@ -18,9 +18,6 @@ import org.bukkit.block.Sign import org.bukkit.block.data.BlockData import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set import kotlin.math.min class StarshipFactoryPrinter( @@ -183,7 +180,7 @@ class StarshipFactoryPrinter( val blockZ = blockKeyZ(key) world.setNMSBlockData(blockX, blockY, blockZ, data) - if (data.bukkitMaterial == EXTRACTOR_TYPE) NewTransport.addExtractor(world, blockX, blockY, blockZ) + if (data.bukkitMaterial == STANDARD_EXTRACTOR_TYPE) NewTransport.addExtractor(world, blockX, blockY, blockZ) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 326a8ff10d..efcff7fa7a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -6,7 +6,7 @@ import net.horizonsend.ion.server.features.starship.event.build.StarshipBreakBlo import net.horizonsend.ion.server.features.starship.event.build.StarshipPlaceBlockEvent import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -80,20 +80,20 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } fun isExtractor(world: World, x: Int, y: Int, z: Int): Boolean { - return getExtractorManager(world, x, z)?.isExtractor(x, y, z) ?: false + return getExtractorManager(world, x, z)?.isExtractorPresent(x, y, z) ?: false } fun ensureExtractor(world: World, x: Int, y: Int, z: Int) { val type = getBlockTypeSafe(world, x, y, z) ?: return val isExtractor = isExtractor(world, x, y, z) - if (type == EXTRACTOR_TYPE && !isExtractor) addExtractor(world, x, y, z) - if (type != EXTRACTOR_TYPE && isExtractor) removeExtractor(world, x, y, z) + if (type == STANDARD_EXTRACTOR_TYPE && !isExtractor) addExtractor(world, x, y, z) + if (type != STANDARD_EXTRACTOR_TYPE && isExtractor) removeExtractor(world, x, y, z) } fun handleBlockEvent(world: World, x: Int, y: Int, z: Int, previousType: Material?, newType: Material) = Tasks.async { invalidateCache(world, x, y, z) - if (previousType == EXTRACTOR_TYPE && newType != EXTRACTOR_TYPE) return@async removeExtractor(world, x, y, z) - if (newType == EXTRACTOR_TYPE) return@async addExtractor(world, x, y, z) + if (previousType == STANDARD_EXTRACTOR_TYPE && newType != STANDARD_EXTRACTOR_TYPE) return@async removeExtractor(world, x, y, z) + if (newType == STANDARD_EXTRACTOR_TYPE) return@async addExtractor(world, x, y, z) } @EventHandler diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 3e01fe443f..de443aab74 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -22,7 +23,7 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag } override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != EXTRACTOR_TYPE) return false + if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != STANDARD_EXTRACTOR_TYPE) return false if (!manager.chunk.isInBounds(x, y, z)) { IonServer.slF4JLogger.warn("Extractor manager of ${manager.chunk} tried to register an extractor outside its bounds!") return false @@ -47,7 +48,7 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return extractors.remove(key) } - override fun isExtractor(key: BlockKey): Boolean = synchronized(mutex) { + override fun isExtractorPresent(key: BlockKey): Boolean = synchronized(mutex) { return extractors.contains(key) } @@ -72,7 +73,7 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag val minBlockZ = snapshot.z.shl(4) for (x in 0..15) for (z in 0..15) for (y in manager.chunk.world.minHeight..snapshot.getHighestBlockYAt(x, z)) { - if (snapshot.getBlockType(x, y, z) != EXTRACTOR_TYPE) continue + if (snapshot.getBlockType(x, y, z) != STANDARD_EXTRACTOR_TYPE) continue val key = toBlockKey(x + minBlockX, y, z + minBlockZ) extractors[key] = ExtractorData(key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index e2a1378c7f..a70e267b99 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -1,12 +1,14 @@ package net.horizonsend.ion.server.features.transport.manager.extractors -import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Material +import org.bukkit.block.data.BlockData abstract class ExtractorManager { abstract fun getExtractors(): Collection @@ -17,29 +19,30 @@ abstract class ExtractorManager { abstract fun removeExtractor(key: BlockKey): ExtractorData? abstract fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? - fun isExtractor(x: Int, y: Int, z: Int): Boolean = isExtractor(toBlockKey(x, y, z)) - abstract fun isExtractor(key: BlockKey): Boolean + /** + * Returns whether an extractor is present at this location + **/ + fun isExtractorPresent(x: Int, y: Int, z: Int): Boolean = isExtractorPresent(toBlockKey(x, y, z)) + + /** + * Returns whether an extractor is present at this location + **/ + abstract fun isExtractorPresent(key: BlockKey): Boolean companion object { - val EXTRACTOR_TYPE = Material.CRAFTING_TABLE - } + val STANDARD_EXTRACTOR_TYPE = Material.CRAFTING_TABLE - open fun onLoad() {} - open fun save() {} + fun getExtractorData(data: BlockData, pos: BlockKey): ExtractorData? { + if (data.material == STANDARD_EXTRACTOR_TYPE) return ExtractorData(pos) - class ExtractorData(val pos: BlockKey) { - private var lastTicked = System.currentTimeMillis() + val customBlock = CustomBlocks.getByBlockData(data) - private fun getDelta(time: Long): Double { - val diff = time - lastTicked - return (diff.toDouble() / transportSettings().extractorConfiguration.extractorTickIntervalMS.toDouble()) - } - fun markTicked(): Double { - val now = System.currentTimeMillis() - val delta = getDelta(now) - lastTicked = now - return delta + + return null } } + + open fun onLoad() {} + open fun save() {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index de460c662d..fa18815b61 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -20,13 +21,13 @@ class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager return extractors.values } - override fun isExtractor(key: BlockKey): Boolean { + override fun isExtractorPresent(key: BlockKey): Boolean { return extractors.contains(key) } /** Returns true if an extractor was registered */ override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - if (ensureExtractor && getBlockTypeSafe(manager.starship.world, x, y, z) != EXTRACTOR_TYPE) return false + if (ensureExtractor && getBlockTypeSafe(manager.starship.world, x, y, z) != STANDARD_EXTRACTOR_TYPE) return false // Store extractors via local coordinates val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt new file mode 100644 index 0000000000..1ed2f0a897 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt @@ -0,0 +1,20 @@ +package net.horizonsend.ion.server.features.transport.manager.extractors.data + +import net.horizonsend.ion.server.configuration.ConfigurationFiles +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +open class ExtractorData(val pos: BlockKey) { + private var lastTicked = System.currentTimeMillis() + + private fun getDelta(time: Long): Double { + val diff = time - lastTicked + return (diff.toDouble() / ConfigurationFiles.transportSettings().extractorConfiguration.extractorTickIntervalMS.toDouble()) + } + + fun markTicked(): Double { + val now = System.currentTimeMillis() + val delta = getDelta(now) + lastTicked = now + return delta + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt new file mode 100644 index 0000000000..8c2f295d28 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt @@ -0,0 +1,6 @@ +package net.horizonsend.ion.server.features.transport.manager.extractors.data + +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +class ItemExtractorData(pos: BlockKey) : ExtractorData(pos) { +} From da04a713fd75ddfc29c156d3b0559f210c249089 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 13:30:33 -0600 Subject: [PATCH 418/500] Move extractor type check from material to block data --- .../command/qol/FixExtractorsCommand.kt | 5 +-- .../custom/blocks/CustomExtractorBlock.kt | 26 +++++++++++++ .../factory/StarshipFactoryPrinter.kt | 7 +++- .../server/features/transport/NewTransport.kt | 38 ++++++++++++------- .../extractors/ChunkExtractorManager.kt | 15 +++++--- .../manager/extractors/ExtractorManager.kt | 5 ++- .../extractors/ShipExtractorManager.kt | 10 +++-- .../persistence/MetaDataContainer.kt | 6 +-- .../persistence/PDCSerializers.kt | 8 ++++ 9 files changed, 89 insertions(+), 31 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt index 9ddd4ae6fc..4020e6e5aa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/FixExtractorsCommand.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.server.command.SLCommand import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.miscellaneous.utils.getSelection import org.bukkit.entity.Player @@ -35,8 +35,7 @@ object FixExtractorsCommand : SLCommand() { val block = sender.world.getBlockAt(x, y, z) - if (block.type != STANDARD_EXTRACTOR_TYPE) continue - + if (!ExtractorManager.isExtractorData(block.blockData)) continue if (NewTransport.isExtractor(sender.world, x, y, z)) continue count++ diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt new file mode 100644 index 0000000000..1857fe1d4a --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.custom.blocks + +import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.Block +import org.bukkit.block.data.BlockData +import org.bukkit.event.player.PlayerInteractEvent +import java.util.function.Supplier + +abstract class CustomExtractorBlock( + identifier: String, + blockData: BlockData, + drops: BlockLoot, + customBlockItem: Supplier, + val guiProvider: (Block, PlayerInteractEvent) -> Unit, + +) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { + abstract fun createExtractorData(pos: BlockKey): ExtractorData + + override fun onRightClick(event: PlayerInteractEvent, block: Block) { + guiProvider.invoke(block, event) + } + + +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt index c9fa535cc2..4e995fb82d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactoryPrinter.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.starship.factory import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.miscellaneous.registrations.ShipFactoryMaterialCosts import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKeyY @@ -16,6 +16,7 @@ import net.starlegacy.javautil.SignUtils import org.bukkit.World import org.bukkit.block.Sign import org.bukkit.block.data.BlockData +import org.bukkit.craftbukkit.block.data.CraftBlockData import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import kotlin.math.min @@ -180,7 +181,9 @@ class StarshipFactoryPrinter( val blockZ = blockKeyZ(key) world.setNMSBlockData(blockX, blockY, blockZ, data) - if (data.bukkitMaterial == STANDARD_EXTRACTOR_TYPE) NewTransport.addExtractor(world, blockX, blockY, blockZ) + if (ExtractorManager.isExtractorData(CraftBlockData.fromData(data))) { + NewTransport.addExtractor(world, blockX, blockY, blockZ) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index efcff7fa7a..64f93284bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -6,14 +6,15 @@ import net.horizonsend.ion.server.features.starship.event.build.StarshipBreakBlo import net.horizonsend.ion.server.features.starship.event.build.StarshipPlaceBlockEvent import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager -import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.STANDARD_EXTRACTOR_TYPE +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager.Companion.isExtractorData import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.Tasks -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.World +import org.bukkit.block.data.BlockData import org.bukkit.event.EventHandler import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPistonExtendEvent @@ -84,40 +85,51 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } fun ensureExtractor(world: World, x: Int, y: Int, z: Int) { - val type = getBlockTypeSafe(world, x, y, z) ?: return - val isExtractor = isExtractor(world, x, y, z) - if (type == STANDARD_EXTRACTOR_TYPE && !isExtractor) addExtractor(world, x, y, z) - if (type != STANDARD_EXTRACTOR_TYPE && isExtractor) removeExtractor(world, x, y, z) + val type = getBlockDataSafe(world, x, y, z) ?: return + + val isExtractorPresent = this@NewTransport.isExtractor(world, x, y, z) + val isExtractor = isExtractorData(type) + + if (isExtractor && !isExtractorPresent) addExtractor(world, x, y, z) + if (!isExtractor && isExtractorPresent) removeExtractor(world, x, y, z) } - fun handleBlockEvent(world: World, x: Int, y: Int, z: Int, previousType: Material?, newType: Material) = Tasks.async { + fun handleBlockEvent(world: World, x: Int, y: Int, z: Int, previousData: BlockData, newData: BlockData) = Tasks.async { invalidateCache(world, x, y, z) - if (previousType == STANDARD_EXTRACTOR_TYPE && newType != STANDARD_EXTRACTOR_TYPE) return@async removeExtractor(world, x, y, z) - if (newType == STANDARD_EXTRACTOR_TYPE) return@async addExtractor(world, x, y, z) + + if (isExtractorData(previousData) && !isExtractorData(newData)) { + removeExtractor(world, x, y, z) + return@async + } + + if (isExtractorData(newData)) { + addExtractor(world, x, y, z) + return@async + } } @EventHandler fun onPlayerBlockPlace(event: BlockPlaceEvent) { val block = event.block - handleBlockEvent(block.world, block.x, block.y, block.z, event.blockReplacedState.type, block.type) + handleBlockEvent(block.world, block.x, block.y, block.z, event.blockReplacedState.blockData, block.blockData) } @EventHandler fun onPlayerBlockBreak(event: BlockBreakEvent) { val block = event.block - handleBlockEvent(block.world, block.x, block.y, block.z, block.type, Material.AIR) + handleBlockEvent(block.world, block.x, block.y, block.z, block.blockData, Material.AIR.createBlockData()) } @EventHandler fun onShipBlockPlace(event: StarshipPlaceBlockEvent) { val block = event.block - handleBlockEvent(block.world, block.x, block.y, block.z, Material.AIR, block.type) + handleBlockEvent(block.world, block.x, block.y, block.z, Material.AIR.createBlockData(), block.blockData) } @EventHandler fun onShipBlockBreak(event: StarshipBreakBlockEvent) { val block = event.block - handleBlockEvent(block.world, block.x, block.y, block.z, event.block.type, Material.AIR) + handleBlockEvent(block.world, block.x, block.y, block.z, event.block.blockData, Material.AIR.createBlockData()) } @EventHandler diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index de443aab74..a6e7e138f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -7,8 +7,9 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.data.Ext import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.persistence.PersistentDataType class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManager() { @@ -23,15 +24,19 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag } override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - if (ensureExtractor && getBlockTypeSafe(manager.chunk.world, x, y, z) != STANDARD_EXTRACTOR_TYPE) return false + val blockData = getBlockDataSafe(manager.chunk.world, x, y, z) ?: return false + val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) + if (!manager.chunk.isInBounds(x, y, z)) { IonServer.slF4JLogger.warn("Extractor manager of ${manager.chunk} tried to register an extractor outside its bounds!") return false } - val key = toBlockKey(x, y, z) + + val data = getExtractorData(blockData, key) + if (data == null) return false synchronized(mutex) { - extractors[key] = ExtractorData(key) + extractors[key] = data } needsSave = true @@ -73,7 +78,7 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag val minBlockZ = snapshot.z.shl(4) for (x in 0..15) for (z in 0..15) for (y in manager.chunk.world.minHeight..snapshot.getHighestBlockYAt(x, z)) { - if (snapshot.getBlockType(x, y, z) != STANDARD_EXTRACTOR_TYPE) continue + if (!isExtractorData(snapshot.getBlockData(x, y, z))) continue val key = toBlockKey(x + minBlockX, y, z + minBlockZ) extractors[key] = ExtractorData(key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index a70e267b99..43d4806b7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.custom.blocks.CustomExtractorBlock import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX @@ -31,13 +32,13 @@ abstract class ExtractorManager { companion object { val STANDARD_EXTRACTOR_TYPE = Material.CRAFTING_TABLE + fun isExtractorData(data: BlockData): Boolean = data.material == STANDARD_EXTRACTOR_TYPE || CustomBlocks.getByBlockData(data) is CustomExtractorBlock fun getExtractorData(data: BlockData, pos: BlockKey): ExtractorData? { if (data.material == STANDARD_EXTRACTOR_TYPE) return ExtractorData(pos) val customBlock = CustomBlocks.getByBlockData(data) - - + if (customBlock is CustomExtractorBlock) return customBlock.createExtractorData(pos) return null } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index fa18815b61..19b7af0076 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.getBlockTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager() { var extractors = Long2ObjectOpenHashMap() @@ -27,11 +27,15 @@ class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager /** Returns true if an extractor was registered */ override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - if (ensureExtractor && getBlockTypeSafe(manager.starship.world, x, y, z) != STANDARD_EXTRACTOR_TYPE) return false + val blockData = getBlockDataSafe(manager.starship.world, x, y, z) ?: return false // Store extractors via local coordinates val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) - extractors[key] = ExtractorData(key) + + val data = getExtractorData(blockData, key) + if (data == null) return false + + extractors[key] = data return true } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt index 3c20d1b955..c80c97ea5d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/MetaDataContainer.kt @@ -4,9 +4,9 @@ import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -data class MetaDataContainer>( - val persistentDataType: C, - val data: V +data class MetaDataContainer>( + val persistentDataType: S, + val data: C ) { companion object : PersistentDataType> { override fun getPrimitiveType(): Class = PersistentDataContainer::class.java diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt index dca6e6f20c..6afb5eeaeb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt @@ -7,9 +7,11 @@ import kotlin.reflect.KClass object PDCSerializers { private val registeredSerializers = mutableMapOf>() + private val typedSerialized = mutableMapOf, RegisteredSerializer<*>>() fun > register(serializer: T): T { registeredSerializers[serializer.identifier] = serializer + typedSerialized[serializer.complexType] = serializer return serializer } @@ -30,4 +32,10 @@ object PDCSerializers { return MetaDataContainer(this, deserialize(data, context)) } } + + fun pack(data: C): MetaDataContainer> { + @Suppress("UNCHECKED_CAST") + val serializer = (typedSerialized[data::class] as? RegisteredSerializer) ?: throw NoSuchElementException("No serialier found for ${data::class.simpleName}") + return MetaDataContainer(serializer, data) + } } From 78492955833ad5de4d5cd63d2aea2da3c5cf2777 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:08:13 -0600 Subject: [PATCH 419/500] Change up extractor storage --- .../extractors/ChunkExtractorManager.kt | 27 ++++++++++++---- .../manager/extractors/ExtractorManager.kt | 2 +- .../extractors/data/AdvancedExtractorData.kt | 14 ++++++++ .../manager/extractors/data/ExtractorData.kt | 4 ++- .../extractors/data/ItemExtractorData.kt | 6 ---- .../persistence/ListMetaDataContainerType.kt | 32 +++++++++++++++++++ .../persistence/NamespacedKeys.kt | 3 +- 7 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index a6e7e138f4..667af338bb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -3,7 +3,10 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager +import net.horizonsend.ion.server.features.transport.manager.extractors.data.AdvancedExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData.StandardExtractorData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.ListMetaDataContainerType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -58,18 +61,31 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag } override fun onLoad() { - val existing = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY) + val standard = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.STANDARD_EXTRACTORS, PersistentDataType.LONG_ARRAY) + val complex = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.COMPLEX_EXTRACTORS, ListMetaDataContainerType) - if (existing == null) { + if (standard == null || complex == null) { loadFromChunk() return } - synchronized(mutex) { existing.associateWithTo(extractors) { ExtractorData(it) } } + synchronized(mutex) { + standard.associateWithTo(extractors) { StandardExtractorData(it) } + complex.associateTo(extractors) { it.data as ExtractorData; it.data.pos to it.data } + } } override fun save() { - manager.chunk.inner.persistentDataContainer.set(NamespacedKeys.EXTRACTORS, PersistentDataType.LONG_ARRAY, extractors.keys.toLongArray()) + val pdc = manager.chunk.inner.persistentDataContainer + val standard = Long2ObjectOpenHashMap() + extractors.filterTo(standard) { entry -> entry.value is StandardExtractorData } + + pdc.set(NamespacedKeys.STANDARD_EXTRACTORS, PersistentDataType.LONG_ARRAY, standard.keys.toLongArray()) + + val complex = extractors.values.filterIsInstance>() + val serialized = complex.map { it.asMetaDataContainer() } + + pdc.set(NamespacedKeys.COMPLEX_EXTRACTORS, ListMetaDataContainerType, serialized) } private fun loadFromChunk() = Tasks.async { @@ -80,10 +96,9 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag for (x in 0..15) for (z in 0..15) for (y in manager.chunk.world.minHeight..snapshot.getHighestBlockYAt(x, z)) { if (!isExtractorData(snapshot.getBlockData(x, y, z))) continue val key = toBlockKey(x + minBlockX, y, z + minBlockZ) - extractors[key] = ExtractorData(key) + extractors[key] = StandardExtractorData(key) } - save() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index 43d4806b7b..eb2e967564 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -35,7 +35,7 @@ abstract class ExtractorManager { fun isExtractorData(data: BlockData): Boolean = data.material == STANDARD_EXTRACTOR_TYPE || CustomBlocks.getByBlockData(data) is CustomExtractorBlock fun getExtractorData(data: BlockData, pos: BlockKey): ExtractorData? { - if (data.material == STANDARD_EXTRACTOR_TYPE) return ExtractorData(pos) + if (data.material == STANDARD_EXTRACTOR_TYPE) return ExtractorData.StandardExtractorData(pos) val customBlock = CustomBlocks.getByBlockData(data) if (customBlock is CustomExtractorBlock) return customBlock.createExtractorData(pos) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt new file mode 100644 index 0000000000..c5e0d999dd --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.transport.manager.extractors.data + +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +abstract class AdvancedExtractorData( + pos: BlockKey, + val metaData: C +) : ExtractorData(pos) { + abstract val serializer: PDCSerializers.RegisteredSerializer + + fun asMetaDataContainer(): MetaDataContainer> = MetaDataContainer(serializer, metaData) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt index 1ed2f0a897..60f049e9e4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorData.kt @@ -3,7 +3,7 @@ package net.horizonsend.ion.server.features.transport.manager.extractors.data import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -open class ExtractorData(val pos: BlockKey) { +abstract class ExtractorData(val pos: BlockKey) { private var lastTicked = System.currentTimeMillis() private fun getDelta(time: Long): Double { @@ -17,4 +17,6 @@ open class ExtractorData(val pos: BlockKey) { lastTicked = now return delta } + + class StandardExtractorData(key: BlockKey) : ExtractorData(key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt deleted file mode 100644 index 8c2f295d28..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt +++ /dev/null @@ -1,6 +0,0 @@ -package net.horizonsend.ion.server.features.transport.manager.extractors.data - -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey - -class ItemExtractorData(pos: BlockKey) : ExtractorData(pos) { -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt new file mode 100644 index 0000000000..52f0921445 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt @@ -0,0 +1,32 @@ +package net.horizonsend.ion.server.miscellaneous.registrations.persistence + +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +object ListMetaDataContainerType : PersistentDataType, List>> { + @Suppress("UNCHECKED_CAST") + override fun getPrimitiveType(): Class> = List::class.java as Class> + @Suppress("UNCHECKED_CAST") + override fun getComplexType(): Class>> = List::class.java as Class>> + + override fun toPrimitive( + complex: List>, + context: PersistentDataAdapterContext, + ): List { + return PersistentDataType.LIST.dataContainers().toPrimitive( + complex.map { container -> MetaDataContainer.toPrimitive(container, context) }, + context + ) + } + + override fun fromPrimitive( + primitive: List, + context: PersistentDataAdapterContext, + ): List> { + return PersistentDataType.LIST.dataContainers().fromPrimitive( + primitive, + context + ).map { container -> MetaDataContainer.fromPrimitive(container, context) } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index d5560d6fa8..3e4397ffa8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -99,7 +99,8 @@ object NamespacedKeys { val STORED_MULTIBLOCK_ENTITIES = key("stored_multiblock_entities") val STORED_MULTIBLOCK_ENTITIES_OLD = key("stored_multiblock_entities_old") - val EXTRACTORS = key("extractors") + val STANDARD_EXTRACTORS = key("standard_extractors") + val COMPLEX_EXTRACTORS = key("complex_extractors") val NODE_TYPE = key("node_type") From f0ddb189933bb82b5cf7733221b28286ad0753b7 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 16:28:06 -0600 Subject: [PATCH 420/500] Add item extractor --- .../features/custom/blocks/CustomBlocks.kt | 5 ++- .../extractor/AdvancedItemExtractorBlock.kt | 26 +++++++++++ .../{ => extractor}/CustomExtractorBlock.kt | 16 ++++--- .../custom/items/CustomItemRegistry.kt | 2 + .../server/features/transport/NewTransport.kt | 13 +++--- .../features/transport/items/SortingOrder.kt | 14 ++++++ .../extractors/ChunkExtractorManager.kt | 19 ++++++-- .../manager/extractors/ExtractorManager.kt | 2 +- .../extractors/data/AdvancedExtractorData.kt | 6 +-- .../extractors/data/ExtractorMetaData.kt | 9 ++++ .../extractors/data/ItemExtractorData.kt | 44 +++++++++++++++++++ .../server/features/world/chunk/IonChunk.kt | 2 +- .../persistence/ListMetaDataContainerType.kt | 7 ++- .../persistence/NamespacedKeys.kt | 4 ++ .../persistence/PDCSerializers.kt | 6 +++ 15 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/{ => extractor}/CustomExtractorBlock.kt (56%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorMetaData.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 9c54abace4..5b0914cf24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.custom.blocks import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import net.horizonsend.ion.server.features.custom.blocks.extractor.AdvancedItemExtractorBlock import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC @@ -199,12 +200,14 @@ object CustomBlocks { ) ) { CustomItemRegistry.CRUISER_REACTOR_CORE }) - private fun customItemDrop(customItem: Supplier, amount: Int = 1): Supplier> { + fun customItemDrop(customItem: Supplier, amount: Int = 1): Supplier> { return customItem.map { item -> listOf(item.constructItemStack(amount)) } } val MULTIBLOCK_WORKBENCH = register(MultiblockWorkbench) + val ADVANCED_ITEM_EXTRACTOR = register(AdvancedItemExtractorBlock) + fun customItemDrop(identifier: String, amount: Int = 1): Supplier> { val customItem = CustomItemRegistry.getByIdentifier(identifier)?.constructItemStack() ?: return Supplier { listOf() } customItem.amount = amount diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt new file mode 100644 index 0000000000..1fd3e98e42 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -0,0 +1,26 @@ +package net.horizonsend.ion.server.features.custom.blocks.extractor + +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.mushroomBlockData +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.BlockFace.DOWN +import org.bukkit.block.BlockFace.NORTH + +object AdvancedItemExtractorBlock : CustomExtractorBlock( + "ADVANCED_ITEM_EXTRACTOR", + mushroomBlockData(setOf(NORTH, DOWN, NORTH)), + BlockLoot( + requiredTool = { BlockLoot.Tool.PICKAXE }, + drops = customItemDrop(CustomItemRegistry::ADVANCED_ITEM_EXTRACTOR) + ), + CustomItemRegistry::ADVANCED_ITEM_EXTRACTOR, + { block, event -> } +) { + override fun createExtractorData(pos: BlockKey): ExtractorData { + return ItemExtractorData(pos, ItemExtractorData.ItemExtractorMetaData(pos)) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt similarity index 56% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index 1857fe1d4a..e3288631b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -1,5 +1,7 @@ -package net.horizonsend.ion.server.features.custom.blocks +package net.horizonsend.ion.server.features.custom.blocks.extractor +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -9,13 +11,13 @@ import org.bukkit.event.player.PlayerInteractEvent import java.util.function.Supplier abstract class CustomExtractorBlock( - identifier: String, - blockData: BlockData, - drops: BlockLoot, - customBlockItem: Supplier, - val guiProvider: (Block, PlayerInteractEvent) -> Unit, + identifier: String, + blockData: BlockData, + drops: BlockLoot, + customBlockItem: Supplier, + val guiProvider: (Block, PlayerInteractEvent) -> Unit, -) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { + ) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { abstract fun createExtractorData(pos: BlockKey): ExtractorData override fun onRightClick(event: PlayerInteractEvent, block: Block) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index 094af85e3f..0141c18175 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -329,6 +329,8 @@ object CustomItemRegistry : IonServerComponent() { val WRENCH = register(Wrench) + val ADVANCED_ITEM_EXTRACTOR = customBlockItem("ADVANCED_ITEM_EXTRACTOR", "tool/multiblock_workbench", text("Advanced Item Extractor"), CustomBlocks::ADVANCED_ITEM_EXTRACTOR) + private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( text("$tierName ", tierColor), text("Power ", GOLD), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 64f93284bf..be62a38d26 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -16,6 +16,7 @@ import org.bukkit.Material import org.bukkit.World import org.bukkit.block.data.BlockData import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPistonExtendEvent import org.bukkit.event.block.BlockPistonRetractEvent @@ -108,31 +109,31 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun onPlayerBlockPlace(event: BlockPlaceEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, event.blockReplacedState.blockData, block.blockData) } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun onPlayerBlockBreak(event: BlockBreakEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, block.blockData, Material.AIR.createBlockData()) } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun onShipBlockPlace(event: StarshipPlaceBlockEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, Material.AIR.createBlockData(), block.blockData) } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun onShipBlockBreak(event: StarshipBreakBlockEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, event.block.blockData, Material.AIR.createBlockData()) } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun handlePistonExtend(event: BlockPistonExtendEvent) { val piston = event.block Tasks.sync { @@ -142,7 +143,7 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } } - @EventHandler + @EventHandler(priority = EventPriority.MONITOR) fun handlePistonRetract(event: BlockPistonRetractEvent) { val piston = event.block Tasks.sync { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt new file mode 100644 index 0000000000..2ca8329b8f --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt @@ -0,0 +1,14 @@ +package net.horizonsend.ion.server.features.transport.items + +import com.manya.pdc.base.EnumDataType + +enum class SortingOrder { + NEAREST_FIRST, + ROUND_ROBIN, + FARTHEST_FIRST, + RANDOM; + + companion object { + val serializationType = EnumDataType(SortingOrder::class.java) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 667af338bb..4e889a343e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManag import net.horizonsend.ion.server.features.transport.manager.extractors.data.AdvancedExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData.StandardExtractorData +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.ListMetaDataContainerType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -62,16 +63,26 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag override fun onLoad() { val standard = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.STANDARD_EXTRACTORS, PersistentDataType.LONG_ARRAY) - val complex = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.COMPLEX_EXTRACTORS, ListMetaDataContainerType) + + val complex = runCatching { manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.COMPLEX_EXTRACTORS, ListMetaDataContainerType) } + .onFailure { exception -> IonServer.slF4JLogger.error("There was an error deserializing complex extractor data: $exception"); exception.printStackTrace() } + .getOrNull() if (standard == null || complex == null) { loadFromChunk() return } - synchronized(mutex) { - standard.associateWithTo(extractors) { StandardExtractorData(it) } - complex.associateTo(extractors) { it.data as ExtractorData; it.data.pos to it.data } + runCatching { + synchronized(mutex) { + standard.associateWithTo(extractors) { StandardExtractorData(it) } + complex.associateTo(extractors) { it.data as ExtractorMetaData; it.data.key to it.data.toExtractorData() } + } + }.onFailure { exception -> + IonServer.slF4JLogger.error("There was an error loading complex extractor data: $exception") + exception.printStackTrace() + + loadFromChunk() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index eb2e967564..3a76c73520 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -1,7 +1,7 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.custom.blocks.CustomExtractorBlock +import net.horizonsend.ion.server.features.custom.blocks.extractor.CustomExtractorBlock import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt index c5e0d999dd..fbc7011d6f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/AdvancedExtractorData.kt @@ -4,11 +4,11 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDa import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -abstract class AdvancedExtractorData( +abstract class AdvancedExtractorData( pos: BlockKey, val metaData: C ) : ExtractorData(pos) { - abstract val serializer: PDCSerializers.RegisteredSerializer + abstract val metaSerializer: PDCSerializers.RegisteredSerializer - fun asMetaDataContainer(): MetaDataContainer> = MetaDataContainer(serializer, metaData) + fun asMetaDataContainer(): MetaDataContainer> = MetaDataContainer(metaSerializer, metaData) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorMetaData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorMetaData.kt new file mode 100644 index 0000000000..8176e509a3 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ExtractorMetaData.kt @@ -0,0 +1,9 @@ +package net.horizonsend.ion.server.features.transport.manager.extractors.data + +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey + +interface ExtractorMetaData { + val key: BlockKey + + fun toExtractorData(): ExtractorData +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt new file mode 100644 index 0000000000..ffeb253759 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt @@ -0,0 +1,44 @@ +package net.horizonsend.ion.server.features.transport.manager.extractors.data + +import net.horizonsend.ion.server.features.transport.items.SortingOrder +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +class ItemExtractorData(pos: BlockKey, metaData: ItemExtractorMetaData) : AdvancedExtractorData(pos, metaData) { + override val metaSerializer: PDCSerializers.RegisteredSerializer = PDCSerializers.ITEM_EXTRACTOR_METADATA + + data class ItemExtractorMetaData( + override val key: BlockKey, + val sortingOrder: SortingOrder = SortingOrder.NEAREST_FIRST + ) : ExtractorMetaData { + override fun toExtractorData(): ExtractorData { + return ItemExtractorData(key, this) + } + + companion object : PDCSerializers.RegisteredSerializer("ITEM_EXTRACTOR_METADATA", ItemExtractorMetaData::class) { + override fun toPrimitive( + complex: ItemExtractorMetaData, + context: PersistentDataAdapterContext, + ): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + pdc.set(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG, complex.key) + pdc.set(NamespacedKeys.SORTING_ORDER, SortingOrder.serializationType, complex.sortingOrder) + return pdc + } + + override fun fromPrimitive( + primitive: PersistentDataContainer, + context: PersistentDataAdapterContext, + ): ItemExtractorMetaData { + return ItemExtractorMetaData( + primitive.get(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG)!!, + primitive.getOrDefault(NamespacedKeys.SORTING_ORDER, SortingOrder.serializationType, SortingOrder.NEAREST_FIRST) + ) + } + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 9ff9ffdd2d..7e57544528 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -113,7 +113,7 @@ class IonChunk(val inner: Chunk) { val chunk = event.chunk if (chunk.world.ion.isChunkLoaded(key)) return - val ionChunk = registerChunk(chunk) + registerChunk(chunk) } catch (e: Throwable) { log.info("Problem when loading IonChunk ${event.chunk.x} ${event.chunk.z} in ${event.chunk.world.name}: ") e.printStackTrace() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt index 52f0921445..350b61477d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/ListMetaDataContainerType.kt @@ -1,10 +1,11 @@ package net.horizonsend.ion.server.miscellaneous.registrations.persistence +import org.bukkit.persistence.ListPersistentDataType import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -object ListMetaDataContainerType : PersistentDataType, List>> { +object ListMetaDataContainerType : ListPersistentDataType> { @Suppress("UNCHECKED_CAST") override fun getPrimitiveType(): Class> = List::class.java as Class> @Suppress("UNCHECKED_CAST") @@ -29,4 +30,8 @@ object ListMetaDataContainerType : PersistentDataType MetaDataContainer.fromPrimitive(container, context) } } + + override fun elementType(): PersistentDataType> { + return MetaDataContainer.Companion + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 3e4397ffa8..6341fb60ab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -10,6 +10,8 @@ object NamespacedKeys { val Y = key("y") val Z = key("z") + val BLOCK_KEY = key("block_key") + val AXIS = key("axis") val UP_DOWN = key("up_down") @@ -102,6 +104,8 @@ object NamespacedKeys { val STANDARD_EXTRACTORS = key("standard_extractors") val COMPLEX_EXTRACTORS = key("complex_extractors") + val SORTING_ORDER = key("sorting_order") + val NODE_TYPE = key("node_type") // Fluid storage diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt index 6afb5eeaeb..88f79d6c8b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.miscellaneous.registrations.persistence +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -15,9 +16,14 @@ object PDCSerializers { return serializer } + val ITEM_EXTRACTOR_METADATA = register(ItemExtractorData.ItemExtractorMetaData.Companion) + operator fun get(identifier: String) : RegisteredSerializer<*> = registeredSerializers[identifier]!! abstract class RegisteredSerializer(val identifier: String, val complexType: KClass) : PersistentDataType { + override fun getComplexType(): Class = complexType.java + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + fun serialize(obj: Any, context: PersistentDataAdapterContext): PersistentDataContainer { require(complexType.isInstance(obj)) @Suppress("UNCHECKED_CAST") From 724176d573e337a8ad6a1e4130283402aa9cf7f5 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 17:05:52 -0600 Subject: [PATCH 421/500] Add pick block for custom items --- .../custom/blocks/CustomBlockListeners.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt index a1c976f586..2985c7e656 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt @@ -1,12 +1,15 @@ package net.horizonsend.ion.server.features.custom.blocks +import io.papermc.paper.event.player.PlayerPickItemEvent import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.minecraft.server.network.ServerGamePacketListenerImpl import org.bukkit.GameMode import org.bukkit.Material +import org.bukkit.attribute.Attribute import org.bukkit.block.data.BlockData import org.bukkit.enchantments.Enchantment import org.bukkit.event.EventHandler @@ -16,6 +19,7 @@ import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.player.PlayerInteractEvent import java.util.concurrent.ConcurrentHashMap +import kotlin.math.roundToInt object CustomBlockListeners : SLEventListener() { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -77,4 +81,51 @@ object CustomBlockListeners : SLEventListener() { else -> return } } + + // Avoid magic string + private val entityPickMethodName = ServerGamePacketListenerImpl::handlePickItemFromEntity.name + + @EventHandler + fun onPlayerPickBlock(event: PlayerPickItemEvent) { + if (Thread.currentThread().stackTrace.any { element -> element.methodName == entityPickMethodName }) return + val player = event.player + + val targetedBlock = player.getTargetBlockExact(player.getAttribute(Attribute.BLOCK_INTERACTION_RANGE)?.value?.roundToInt() ?: 5) ?: return + val customBlock = CustomBlocks.getByBlockData(targetedBlock.blockData) ?: return + val customBlockItem = customBlock.customItem.constructItemStack() + + // Source slot is for survival, when taking the item from the slot in the inventory, -1 if it is not present, e.g. creative mode + // Target slot is the slot in the hotbar that the picked block will go to + + if (player.gameMode == GameMode.CREATIVE) { + if (event.player.inventory.containsAtLeast(customBlockItem, 1)) { + val index = event.player.inventory.indexOfFirst { stack -> stack?.isSimilar(customBlockItem) == true } + + // If in hotbar, jump to slot, else grab from inventory + if (index in 0..8) { + event.targetSlot = index + event.sourceSlot = index + } else { + event.sourceSlot = index + } + } else { + event.isCancelled = true + event.player.inventory.setItem(event.targetSlot, customBlockItem) + } + } + + if (player.gameMode == GameMode.SURVIVAL) { + if (event.player.inventory.containsAtLeast(customBlockItem, 1)) { + val index = event.player.inventory.indexOfFirst { stack -> stack?.isSimilar(customBlockItem) == true } + + // If in hotbar, jump to slot, else grab from inventory + if (index in 0..8) { + event.targetSlot = index + event.sourceSlot = index + } else { + event.sourceSlot = index + } + } + } + } } From e1f1e21dcbe03aac01c7b5c9b826506e4100bc31 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 20:03:12 -0600 Subject: [PATCH 422/500] expand gui util --- .../extractor/AdvancedItemExtractorBlock.kt | 14 +++++++--- .../blocks/extractor/CustomExtractorBlock.kt | 28 +++++++++++++++---- .../server/features/transport/NewTransport.kt | 4 +-- .../extractors/ChunkExtractorManager.kt | 14 ++++++---- .../manager/extractors/ExtractorManager.kt | 10 ++++--- .../extractors/ShipExtractorManager.kt | 16 +++++++---- 6 files changed, 59 insertions(+), 27 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 1fd3e98e42..9bc96cceb7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -1,16 +1,18 @@ package net.horizonsend.ion.server.features.custom.blocks.extractor +import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.mushroomBlockData import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry -import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.block.Block import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.BlockFace.NORTH +import org.bukkit.entity.Player -object AdvancedItemExtractorBlock : CustomExtractorBlock( +object AdvancedItemExtractorBlock : CustomExtractorBlock( "ADVANCED_ITEM_EXTRACTOR", mushroomBlockData(setOf(NORTH, DOWN, NORTH)), BlockLoot( @@ -18,9 +20,13 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( drops = customItemDrop(CustomItemRegistry::ADVANCED_ITEM_EXTRACTOR) ), CustomItemRegistry::ADVANCED_ITEM_EXTRACTOR, - { block, event -> } + ItemExtractorData::class ) { - override fun createExtractorData(pos: BlockKey): ExtractorData { + override fun createExtractorData(pos: BlockKey): ItemExtractorData { return ItemExtractorData(pos, ItemExtractorData.ItemExtractorMetaData(pos)) } + + override fun openGUI(player: Player, block: Block, extractorData: ItemExtractorData) { + player.success("Workin") + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index e3288631b3..71df993d68 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -4,25 +4,41 @@ import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.Block import org.bukkit.block.data.BlockData +import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import java.util.function.Supplier +import kotlin.reflect.KClass -abstract class CustomExtractorBlock( +abstract class CustomExtractorBlock( identifier: String, blockData: BlockData, drops: BlockLoot, customBlockItem: Supplier, - val guiProvider: (Block, PlayerInteractEvent) -> Unit, - - ) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { - abstract fun createExtractorData(pos: BlockKey): ExtractorData + val extractorDataType: KClass +) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { override fun onRightClick(event: PlayerInteractEvent, block: Block) { - guiProvider.invoke(block, event) + val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return + + val key = toBlockKey(block.x, block.y, block.z) + + val extractorManager = chunk.transportNetwork.extractorManager + val extractorData = extractorManager.getExtractorData(key) ?: extractorManager.registerExtractor(key) + + if (extractorData == null) return + + if (!extractorDataType.isInstance(extractorData)) return + + @Suppress("UNCHECKED_CAST") + openGUI(event.player, block, extractorData as T) } + abstract fun createExtractorData(pos: BlockKey): T + abstract fun openGUI(player: Player, block: Block, extractorData: T) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index be62a38d26..28e1332028 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -73,8 +73,8 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t return IonChunk.getFromWorldCoordinates(world, x, z)?.transportNetwork?.extractorManager } - fun addExtractor(world: World, x: Int, y: Int, z: Int, ensureExtractor: Boolean = false) { - getExtractorManager(world, x, z)?.registerExtractor(x, y, z, ensureExtractor) + fun addExtractor(world: World, x: Int, y: Int, z: Int) { + getExtractorManager(world, x, z)?.registerExtractor(x, y, z) } fun removeExtractor(world: World, x: Int, y: Int, z: Int) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 4e889a343e..7b5fe1d19e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -27,24 +27,24 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return extractors.values } - override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - val blockData = getBlockDataSafe(manager.chunk.world, x, y, z) ?: return false + override fun registerExtractor(x: Int, y: Int, z: Int): ExtractorData? { + val blockData = getBlockDataSafe(manager.chunk.world, x, y, z) ?: return null val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) if (!manager.chunk.isInBounds(x, y, z)) { IonServer.slF4JLogger.warn("Extractor manager of ${manager.chunk} tried to register an extractor outside its bounds!") - return false + return null } val data = getExtractorData(blockData, key) - if (data == null) return false + if (data == null) return null synchronized(mutex) { extractors[key] = data } needsSave = true - return true + return data } override fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? = synchronized(mutex) { @@ -61,6 +61,10 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return extractors.contains(key) } + override fun getExtractorData(key: BlockKey): ExtractorData? { + return extractors[key] + } + override fun onLoad() { val standard = manager.chunk.inner.persistentDataContainer.get(NamespacedKeys.STANDARD_EXTRACTORS, PersistentDataType.LONG_ARRAY) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index 3a76c73520..d24891b550 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -14,8 +14,8 @@ import org.bukkit.block.data.BlockData abstract class ExtractorManager { abstract fun getExtractors(): Collection - fun registerExtractor(key: BlockKey, ensureExtractor: Boolean): Boolean = registerExtractor(getX(key), getY(key), getZ(key), ensureExtractor) - abstract fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean + fun registerExtractor(key: BlockKey): ExtractorData? = registerExtractor(getX(key), getY(key), getZ(key)) + abstract fun registerExtractor(x: Int, y: Int, z: Int): ExtractorData? abstract fun removeExtractor(key: BlockKey): ExtractorData? abstract fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? @@ -30,15 +30,17 @@ abstract class ExtractorManager { **/ abstract fun isExtractorPresent(key: BlockKey): Boolean + abstract fun getExtractorData(key: BlockKey): ExtractorData? + companion object { val STANDARD_EXTRACTOR_TYPE = Material.CRAFTING_TABLE - fun isExtractorData(data: BlockData): Boolean = data.material == STANDARD_EXTRACTOR_TYPE || CustomBlocks.getByBlockData(data) is CustomExtractorBlock + fun isExtractorData(data: BlockData): Boolean = data.material == STANDARD_EXTRACTOR_TYPE || CustomBlocks.getByBlockData(data) is CustomExtractorBlock<*> fun getExtractorData(data: BlockData, pos: BlockKey): ExtractorData? { if (data.material == STANDARD_EXTRACTOR_TYPE) return ExtractorData.StandardExtractorData(pos) val customBlock = CustomBlocks.getByBlockData(data) - if (customBlock is CustomExtractorBlock) return customBlock.createExtractorData(pos) + if (customBlock is CustomExtractorBlock<*>) return customBlock.createExtractorData(pos) return null } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index 19b7af0076..50c3d43c7c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -25,19 +25,23 @@ class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager return extractors.contains(key) } + override fun getExtractorData(key: BlockKey): ExtractorData? { + return extractors[key] + } + /** Returns true if an extractor was registered */ - override fun registerExtractor(x: Int, y: Int, z: Int, ensureExtractor: Boolean): Boolean { - val blockData = getBlockDataSafe(manager.starship.world, x, y, z) ?: return false + override fun registerExtractor(x: Int, y: Int, z: Int): ExtractorData? { + val blockData = getBlockDataSafe(manager.starship.world, x, y, z) ?: return null // Store extractors via local coordinates val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) val data = getExtractorData(blockData, key) - if (data == null) return false + if (data == null) return null extractors[key] = data - return true + return data } override fun removeExtractor(x: Int, y: Int, z: Int): ExtractorData? { @@ -51,7 +55,7 @@ class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager fun loadExtractors() { manager.starship.iterateBlocks { x, y, z -> // If an extractor is added at the starship, remove the one in the world - if (registerExtractor( x, y, z, true)) { + if (registerExtractor( x, y, z) == null) { NewTransport.removeExtractor(manager.starship.world, x, y, z) } } @@ -69,7 +73,7 @@ class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager for (entry in entries) { val worldCoord = toBlockKey(manager.getGlobalCoordinate(toVec3i(entry))) - ionChunk.transportNetwork.extractorManager.registerExtractor(worldCoord, ensureExtractor = true) + ionChunk.transportNetwork.extractorManager.registerExtractor(worldCoord) } } } From 1b98d96987a3cb5b30660f8f4df86656d12e9c3f Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:36:05 -0600 Subject: [PATCH 423/500] add cycling for testing --- .../blocks/extractor/AdvancedItemExtractorBlock.kt | 11 ++++++++++- .../ion/server/features/transport/NewTransport.kt | 6 ++++-- .../manager/extractors/data/ItemExtractorData.kt | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 9bc96cceb7..26449b3ce2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -1,10 +1,12 @@ package net.horizonsend.ion.server.features.custom.blocks.extractor +import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.mushroomBlockData import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry +import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.Block @@ -27,6 +29,13 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( } override fun openGUI(player: Player, block: Block, extractorData: ItemExtractorData) { - player.success("Workin") + val current = extractorData.metaData.sortingOrder + val entires = SortingOrder.entries + player.information("Current: $current") + + val new = if (current.ordinal + 1 > entires.lastIndex) 0 else current.ordinal + 1 + + player.success("New: ${SortingOrder.entries[new]}") + extractorData.metaData.sortingOrder = SortingOrder.entries[new] } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 28e1332028..a40f5318e5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -54,6 +54,8 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t override fun onDisable() { if (::monitorThread.isInitialized) monitorThread.cancel() if (::executor.isInitialized) executor.shutdown() + + saveExtractors() } fun registerTransportManager(manager: TransportManager<*>) { @@ -155,8 +157,8 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t fun saveExtractors() { for (world in Bukkit.getWorlds().map { it.ion }) { - val chunks = world.getAllChunks().values.forEach { chunk -> - chunk.transportNetwork.extractorManager.takeIf { it.needsSave }?.save() + world.getAllChunks().values.forEach { chunk -> + chunk.transportNetwork.extractorManager.save() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt index ffeb253759..8686f63c5b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt @@ -13,7 +13,7 @@ class ItemExtractorData(pos: BlockKey, metaData: ItemExtractorMetaData) : Advanc data class ItemExtractorMetaData( override val key: BlockKey, - val sortingOrder: SortingOrder = SortingOrder.NEAREST_FIRST + var sortingOrder: SortingOrder = SortingOrder.NEAREST_FIRST ) : ExtractorMetaData { override fun toExtractorData(): ExtractorData { return ItemExtractorData(key, this) From f64ede02f684969324244d7c3949ba3933644d9c Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 23 Jan 2025 00:41:59 -0600 Subject: [PATCH 424/500] Build out more item transfer code --- .../command/misc/TransportDebugCommand.kt | 25 ++++-- .../extractor/AdvancedItemExtractorBlock.kt | 8 ++ .../blocks/extractor/CustomExtractorBlock.kt | 10 ++- .../manager/ChunkTransportManager.kt | 18 ++-- .../transport/manager/ShipTransportManager.kt | 14 ++- .../transport/manager/TransportManager.kt | 10 ++- .../nodes/cache/FluidTransportCache.kt | 5 +- .../nodes/cache/ItemTransportCache.kt | 86 ++++++++++++++++++- .../transport/nodes/cache/NodeCacheFactory.kt | 31 ++++++- .../nodes/cache/PowerTransportCache.kt | 5 +- .../transport/nodes/cache/SolarPanelCache.kt | 3 +- .../transport/nodes/cache/TransportCache.kt | 5 +- .../transport/nodes/types/ItemNode.kt | 23 +++++ 13 files changed, 207 insertions(+), 36 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 7fba0fb060..f654066dad 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -7,10 +7,11 @@ import io.papermc.paper.util.StacktraceDeobfuscator import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.command.SLCommand -import net.horizonsend.ion.server.command.admin.IonChunkCommand import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlocks +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import net.horizonsend.ion.server.features.transport.nodes.cache.CacheState +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode @@ -160,7 +161,7 @@ object TransportDebugCommand : SLCommand() { } private fun requireLookingAt(sender: Player, network: (Block) -> TransportCache): Pair { - val targeted = sender.getTargetBlock(null, 10) + val targeted = sender.getTargetBlockExact(10) ?: fail { "No block in range" } val grid = network(targeted) val key = toBlockKey(targeted.x, targeted.y, targeted.z) @@ -180,17 +181,27 @@ object TransportDebugCommand : SLCommand() { sender.information("Targeted node: $node at ${toVec3i(location)}") } - @Subcommand("test extractor test") + @Subcommand("test extractor") fun onTick(sender: Player, type: CacheType) { - val (node, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } + val (_, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } val grid = type.get(chunk) - if (grid.holder.getExtractorManager().isExtractorPresent(location)) IonChunkCommand.fail { "Extractor not targeted" } + if (grid.holder.getExtractorManager().isExtractorPresent(location)) fail { "Extractor not targeted" } + + grid.tickExtractor(location, 1.0, null) + } + + @Subcommand("test item extractor") + fun onTickItem(sender: Player) { + val (_, location) = requireLookingAt(sender) { CacheType.ITEMS.get(it.chunk.ion()) } + val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } + val grid = CacheType.ITEMS.get(chunk) as ItemTransportCache + if (grid.holder.getExtractorManager().isExtractorPresent(location)) fail { "Extractor not targeted" } - grid.tickExtractor(location, 1.0) + grid.handleExtractorTick(location, 1.0, (grid.holder.getExtractorManager().getExtractorData(location) as? ItemExtractorData)?.metaData) } - @Subcommand("test flood test") + @Subcommand("test flood") fun onTestFloodFill(sender: Player, type: CacheType) { sender.information("Trying to find input nodes") val (_, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 26449b3ce2..d9291b8287 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -8,7 +8,11 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.mushroomBl import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.Block import org.bukkit.block.BlockFace.DOWN import org.bukkit.block.BlockFace.NORTH @@ -37,5 +41,9 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( player.success("New: ${SortingOrder.entries[new]}") extractorData.metaData.sortingOrder = SortingOrder.entries[new] + + val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return + val itemCache = CacheType.ITEMS.get(chunk) as ItemTransportCache + itemCache.handleExtractorTick(toBlockKey(block.x, block.y, block.z), 1.0, extractorData.metaData) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index 71df993d68..2ab167c798 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.Block @@ -21,6 +22,7 @@ abstract class CustomExtractorBlock( customBlockItem: Supplier, val extractorDataType: KClass ) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { + val cooldown = PerPlayerCooldown(5L) override fun onRightClick(event: PlayerInteractEvent, block: Block) { val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return @@ -34,8 +36,12 @@ abstract class CustomExtractorBlock( if (!extractorDataType.isInstance(extractorData)) return - @Suppress("UNCHECKED_CAST") - openGUI(event.player, block, extractorData as T) + event.isCancelled = true + + cooldown.tryExec(event.player) { + @Suppress("UNCHECKED_CAST") + openGUI(event.player, block, extractorData as T) + } } abstract fun createExtractorData(pos: BlockKey): T diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index f52155a509..798196f14e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -21,13 +21,19 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager> = arrayOf( + override val cacheHolders: Array> = arrayOf( powerNodeManager, solarPanelManager, itemPipeManager, // fluidNodeManager ) + override val tickedHolders: Array> = arrayOf( + powerNodeManager, + itemPipeManager, +// fluidNodeManager + ) + override fun getInputProvider(): InputManager { return chunk.world.ion.inputManager } @@ -37,12 +43,12 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager> = arrayOf( + override val cacheHolders: Array> = arrayOf( powerNodeManager, solarPanelManager, itemPipeManager, // fluidNodeManager ) + override val tickedHolders: Array> = arrayOf( + powerNodeManager, + itemPipeManager, +// fluidNodeManager + ) + init { load() } fun load() { - networks.forEach { it.handleLoad() } + cacheHolders.forEach { it.handleLoad() } extractorManager.loadExtractors() NewTransport.registerTransportManager(this) } fun release() { - networks.forEach { it.release() } + cacheHolders.forEach { it.release() } NewTransport.removeTransportManager(this) extractorManager.releaseExtractors() } fun displace(movement: StarshipMovement) { - networks.forEach { it.displace(movement) } + cacheHolders.forEach { it.displace(movement) } } override fun getInputProvider(): InputManager { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 71b4c08281..0a080d1d45 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.extractors.data.AdvancedExtractorData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache @@ -16,15 +17,18 @@ abstract class TransportManager> { abstract val itemPipeManager: CacheHolder // abstract val fluidNodeManager: CacheHolder - abstract val networks: Array + abstract val cacheHolders: Array + abstract val tickedHolders: Array abstract fun getInputProvider(): InputManager fun tick() { for (extractor in extractorManager.getExtractors()) { val delta = extractor.markTicked() - powerNodeManager.cache.tickExtractor(extractor.pos, delta) -// fluidNodeManager.cache.tickExtractor(extractor.pos, delta) + + for (network in tickedHolders) { + network.cache.tickExtractor(extractor.pos, delta, (extractor as? AdvancedExtractorData<*>)?.metaData) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index f00077b2d7..ffc73b846d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.fluids.FluidSt import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidStack +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.FilterNode import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode @@ -41,9 +42,9 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) .build() - override fun tickExtractor(location: BlockKey, delta: Double) { NewTransport.executor.submit { + override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { NewTransport.executor.submit { val world = holder.getWorld() - val sources = getExtractorSources(location) { it.isEmpty() } + val sources = getExtractorSourceEntities(location) { it.isEmpty() } val source = sources.randomOrNull() ?: return@submit //TODO take from all if (source.getStoredResources().isEmpty()) return@submit diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 3245e49729..313ae8d30c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -1,26 +1,104 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.server.command.misc.TransportDebugCommand +import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.items.SortingOrder +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.debugAudience +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.core.BlockPos +import net.minecraft.world.Container import org.bukkit.Material +import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.craftbukkit.block.impl.CraftGrindstone +import org.bukkit.craftbukkit.inventory.CraftInventory +import org.bukkit.inventory.Inventory class ItemTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.ITEMS override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) + .addSimpleNode(CustomBlocks.ADVANCED_ITEM_EXTRACTOR, ItemNode.ItemExtractorNode) .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } - .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } + .addSimpleNode(STAINED_GLASS_PANE_TYPES) { _, material -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } + .addSimpleNode(Material.GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) + .addSimpleNode(Material.GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(Material.TINTED_GLASS, ItemNode.WildcardSolidGlassNode) - .addSimpleNode(Material.GLASS, ItemNode.WildcardSolidGlassNode) - .addSimpleNode(Material.GLASS_PANE, ItemNode.WildcardPaneGlassNode) .addDataHandler(Material.GRINDSTONE) { data, key -> ItemNode.ItemMergeNode } + .addSimpleNode( + Material.CHEST, + Material.TRAPPED_CHEST, + Material.BARREL, + Material.FURNACE, + Material.DISPENSER, + Material.DROPPER, + Material.DECORATED_POT + ) { key, _ -> ItemNode.InventoryNode(key) } .build() - override fun tickExtractor(location: BlockKey, delta: Double) { + override fun tickExtractor( + location: BlockKey, + delta: Double, + metaData: ExtractorMetaData?, + ) { + return + NewTransport.executor.submit { + measureOrFallback(TransportDebugCommand.extractorTickTimes) { + handleExtractorTick(location, delta, metaData as? ItemExtractorMetaData) + } + } + } + + fun handleExtractorTick(location: BlockKey, delta: Double, meta: ItemExtractorMetaData?) { + val distributionOrder = meta?.sortingOrder ?: SortingOrder.NEAREST_FIRST + + val sources = getSources(location) + if (sources.isEmpty()) { + println("No source inventories") + return + } + + val destinations: Collection = getNetworkDestinations(location) { node -> + getInventory(node.position) != null + } + + debugAudience.information("Destinations: ${destinations.size}") + } + + fun getInventory(key: BlockKey): Inventory? { + val globalVec = holder.transportManager.getGlobalCoordinate(toVec3i(key)) + val nmsChunk = holder.getWorld().minecraft.getChunkIfLoaded(globalVec.x.shr(4), globalVec.z.shr(4)) ?: return null + val tileEntity = nmsChunk.getBlockEntity(BlockPos(globalVec.x, globalVec.y, globalVec.z)) as? Container ?: return null + + return CraftInventory(tileEntity) + } + + fun getSources(extractorLocation: BlockKey): Set { + val inventories = mutableSetOf() + + for (face in ADJACENT_BLOCK_FACES) { + val inventoryLocation = getRelative(extractorLocation, face) + if (holder.getOrCacheGlobalNode(inventoryLocation) !is ItemNode.InventoryNode) continue + val inv = getInventory(inventoryLocation) ?: continue + if (inv.isEmpty) continue + inventories.add(inv) + } + + return inventories } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 4cf3c892f7..177788587c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,5 +1,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -8,6 +10,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.data.BlockData +import org.bukkit.block.data.MultipleFacing import kotlin.reflect.KClass class NodeCacheFactory private constructor(private val materialHandlers: Map>) { @@ -24,16 +27,31 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map>() - inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node): Builder { + inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node?): Builder { this.materialHandlers[material] = MaterialHandler(T::class, constructor) return this } + inline fun addDataHandler(materials: Iterable, noinline constructor: (T, BlockKey) -> Node): Builder { + for (material in materials) this.materialHandlers[material] = MaterialHandler(T::class, constructor) + return this + } + + inline fun addDataHandler(vararg materials: Material, noinline constructor: (T, BlockKey) -> Node?): Builder { + for (material in materials) this.materialHandlers[material] = MaterialHandler(T::class, constructor) + return this + } + fun addSimpleNode(materials: Iterable, constructor: (BlockKey, Material) -> Node): Builder { for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) } return this } + fun addSimpleNode(vararg materials: Material, constructor: (BlockKey, Material) -> Node): Builder { + for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) } + return this + } + fun addSimpleNode(material: Material, constructor: (BlockKey) -> Node): Builder { this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, key -> constructor(key) } return this @@ -44,6 +62,13 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(Material.BROWN_MUSHROOM_BLOCK) { data, lng -> + if (CustomBlocks.getByBlockData(data) != customBlock) return@addDataHandler null + node + } + } + fun addSimpleNode(materials: Iterable, node: Node): Builder { for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } return this @@ -56,9 +81,9 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(val blockDataClass: KClass, val constructor: (T, BlockKey) -> Node) { + class MaterialHandler(val blockDataClass: KClass, val constructor: (T, BlockKey) -> Node?) { @Synchronized - fun construct(blockData: BlockData, key: BlockKey): Node { + fun construct(blockData: BlockData, key: BlockKey): Node? { @Suppress("UNCHECKED_CAST") return constructor.invoke(blockData as T, key) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 196bdcd571..0d43d7ccfa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFa import net.horizonsend.ion.server.configuration.ConfigurationFiles.transportSettings import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode @@ -39,7 +40,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC .addSimpleNode(NOTE_BLOCK, PowerInputNode) .build() - override fun tickExtractor(location: BlockKey, delta: Double) { + override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { val solarCache = holder.transportManager.solarPanelManager.cache if (solarCache.isSolarPanel(location)) tickSolarPanel(location, delta, solarCache) @@ -50,7 +51,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC measureOrFallback(TransportDebugCommand.extractorTickTimes) { val world = holder.getWorld() - val sources = getExtractorSources(location) { it.powerStorage.isEmpty() } + val sources = getExtractorSourceEntities(location) { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@measureOrFallback //TODO take from all // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt index 335851c1d3..8692805185 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.configuration.ConfigurationFiles +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType @@ -54,5 +55,5 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol return (base * powerRatio * powerMultiplier).roundToInt() } - override fun tickExtractor(location: BlockKey, delta: Double) { } + override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 3616eeabe7..35b22eec06 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -4,6 +4,7 @@ import com.google.common.collect.TreeBasedTable import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.ComplexNode import net.horizonsend.ion.server.features.transport.nodes.types.Node @@ -35,7 +36,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory - abstract fun tickExtractor(location: BlockKey, delta: Double) + abstract fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) fun isCached(at: BlockKey): Boolean = cache.containsKey(at) @@ -140,7 +141,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { Vec3i(-1, 0, -1), ) - inline fun getExtractorSources(extractorLocation: BlockKey, filterNot: (T) -> Boolean): List { + inline fun getExtractorSourceEntities(extractorLocation: BlockKey, filterNot: (T) -> Boolean): List { val sources = mutableListOf() for (face in ADJACENT_BLOCK_FACES) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index dbfb0d1f27..767bacb04e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -3,6 +3,8 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.PipeChannel.entries import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextColor.fromHexString @@ -12,6 +14,21 @@ import org.bukkit.block.BlockFace interface ItemNode : Node { override val cacheType: CacheType get() = CacheType.ITEMS + data class InventoryNode(val position: BlockKey) : ItemNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = false + override fun getTransferableDirections(backwards: BlockFace): Set = setOf() + + override val pathfindingResistance: Double = 0.0 + } + + data object ItemExtractorNode : ItemNode { + override val pathfindingResistance: Double = 0.5 + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = false + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is InventoryNode + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + } + sealed interface ChanneledItemNode { val channel: PipeChannel @@ -81,6 +98,7 @@ interface ItemNode : Node { PURPLE(Material.PURPLE_STAINED_GLASS, Material.PURPLE_STAINED_GLASS_PANE, NamedTextColor.DARK_PURPLE), MAGENTA(Material.MAGENTA_STAINED_GLASS, Material.MAGENTA_STAINED_GLASS_PANE, NamedTextColor.LIGHT_PURPLE), PINK(Material.PINK_STAINED_GLASS, Material.PINK_STAINED_GLASS_PANE, fromHexString("#FFC0CB")!!), + CLEAR(Material.GLASS, Material.GLASS_PANE, NamedTextColor.WHITE), ; @@ -92,5 +110,10 @@ interface ItemNode : Node { operator fun get(material: Material) = byMaterial[material] } + + val displayName = Component.text( + name.split('_').joinToString(separator = " ") { string -> string.replaceFirstChar { ch -> ch.uppercase() } }, + textColor + ) } } From 343500bd37a6ebd31c821804e1c925d6c2e4a811 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 23 Jan 2025 01:05:56 -0600 Subject: [PATCH 425/500] Implement destination methods --- .../features/transport/items/SortingOrder.kt | 35 ++++++++++++++++--- .../extractors/data/ItemExtractorData.kt | 2 ++ .../nodes/cache/ItemTransportCache.kt | 12 +++++-- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt index 2ca8329b8f..9ddcf3c808 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt @@ -1,12 +1,39 @@ package net.horizonsend.ion.server.features.transport.items import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i enum class SortingOrder { - NEAREST_FIRST, - ROUND_ROBIN, - FARTHEST_FIRST, - RANDOM; + NEAREST_FIRST { + override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { + val extractorPosition = toVec3i(extractorData.key) + return destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } + } + }, + ROUND_ROBIN { + override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { + val currentIndex = extractorData.roundRobinIndex + + val nextIndex = (currentIndex + 1) % destinations.size + extractorData.roundRobinIndex = nextIndex + return destinations[nextIndex] + } + }, + FARTHEST_FIRST { + override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { + val extractorPosition = toVec3i(extractorData.key) + return destinations.maxBy { key -> extractorPosition.distance(toVec3i(key)) } + } + }, + RANDOM { + override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { + return destinations.random() + } + }; + + abstract fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey companion object { val serializationType = EnumDataType(SortingOrder::class.java) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt index 8686f63c5b..abbc0cdecd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt @@ -15,6 +15,8 @@ class ItemExtractorData(pos: BlockKey, metaData: ItemExtractorMetaData) : Advanc override val key: BlockKey, var sortingOrder: SortingOrder = SortingOrder.NEAREST_FIRST ) : ExtractorMetaData { + var roundRobinIndex = 0 + override fun toExtractorData(): ExtractorData { return ItemExtractorData(key, this) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 313ae8d30c..9ef899b34a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.items.SortingOrder @@ -55,7 +56,7 @@ class ItemTransportCache(holder: CacheHolder): TransportCach delta: Double, metaData: ExtractorMetaData?, ) { - return +// return NewTransport.executor.submit { measureOrFallback(TransportDebugCommand.extractorTickTimes) { @@ -69,14 +70,19 @@ class ItemTransportCache(holder: CacheHolder): TransportCach val sources = getSources(location) if (sources.isEmpty()) { - println("No source inventories") return } - val destinations: Collection = getNetworkDestinations(location) { node -> + val destinations: List = getNetworkDestinations(location) { node -> getInventory(node.position) != null + }.toList() + + val destination = if (meta != null) distributionOrder.getDestination(meta, destinations) else { + val extractorPosition = toVec3i(location) + destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } } + debugAudience.highlightBlock(toVec3i(destination), 40L) debugAudience.information("Destinations: ${destinations.size}") } From 372d22d8bf17d2146ff51d564499fdf860e83339 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 23 Jan 2025 01:13:42 -0600 Subject: [PATCH 426/500] filter out non non-empty inventories (todo full check) --- .../features/transport/nodes/cache/ItemTransportCache.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 9ef899b34a..a06932d680 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -74,7 +74,8 @@ class ItemTransportCache(holder: CacheHolder): TransportCach } val destinations: List = getNetworkDestinations(location) { node -> - getInventory(node.position) != null + val inventory = getInventory(node.position) + inventory != null && inventory.isEmpty //TODO full }.toList() val destination = if (meta != null) distributionOrder.getDestination(meta, destinations) else { From af534646fd67ea745ad03578150946ecae8791e7 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 23 Jan 2025 01:38:47 -0600 Subject: [PATCH 427/500] Add back filter data structures --- .../features/transport/filters/FilterData.kt | 36 +++++++++++++++++++ .../features/transport/filters/FilterKey.kt | 30 ++++++++++++++++ .../features/transport/filters/FilterType.kt | 32 +++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt new file mode 100644 index 0000000000..6e88f60ba9 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -0,0 +1,36 @@ +package net.horizonsend.ion.server.features.transport.filters + +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +class FilterData( + val isWhitelist: Boolean, + val entries: MutableList> +) { + companion object : PersistentDataType> { + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + override fun getComplexType(): Class> = FilterData::class.java + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*> { + val whitelist = primitive.getOrDefault(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, true) + val entries = primitive.getOrDefault(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()) + val formatted = entries.mapTo(mutableListOf()) { entry -> + FilterKey.fromPrimitive(entry, context) + } + + return FilterData(whitelist, formatted) + } + + override fun toPrimitive(complex: FilterData<*>, context: PersistentDataAdapterContext): PersistentDataContainer { + val data = context.newPersistentDataContainer() + + data.set(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, complex.isWhitelist) + val array = Array(complex.entries.size) { FilterKey.toPrimitive(complex.entries[it], context) } + data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, array) + + return data + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt new file mode 100644 index 0000000000..f8639b1217 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.transport.filters + +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +class FilterKey(val entry: T, val type: FilterType) { + companion object : PersistentDataType> { + override fun getComplexType(): Class> = FilterKey::class.java + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterKey<*> { + val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! + val filterType = FilterType.filterTypes[filterTypeIdentifier]!! + + return FilterKey(filterType.retrieve(primitive)!!, filterType) + } + + override fun toPrimitive(complex: FilterKey<*>, context: PersistentDataAdapterContext): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + val typeIdentifier = complex.type.javaClass.simpleName + + pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) + complex.type.store(pdc, complex.entry) + + return pdc + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt new file mode 100644 index 0000000000..df443dd522 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -0,0 +1,32 @@ +package net.horizonsend.ion.server.features.transport.filters + +import com.manya.pdc.minecraft.ItemStackDataType +import net.horizonsend.ion.server.features.transport.fluids.Fluid +import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +abstract class FilterType(val cacheType: CacheType, val typeClass: Class, val persistentDataType: PersistentDataType<*, T>) { + data object FluidType : FilterType(CacheType.FLUID, Fluid::class.java, FluidPersistentDataType) + data object ItemType : FilterType(CacheType.ITEMS, ItemStack::class.java, ItemStackDataType()) + + fun store(pdc: PersistentDataContainer, data: Any) { + if (!typeClass.isInstance(data)) return + @Suppress("UNCHECKED_CAST") + pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, data as T) + } + + fun retrieve(pdc: PersistentDataContainer): T? { + return pdc.get(NamespacedKeys.FILTER_ENTRY, persistentDataType) + } + + companion object { + val filterTypes = mutableMapOf>( + FluidType.javaClass.simpleName to FluidType, + ItemType.javaClass.simpleName to ItemType, + ) + } +} From 1d06cb7f80e0301d635bd69055ad81b9ff7455e4 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 24 Jan 2025 01:45:21 -0600 Subject: [PATCH 428/500] Add item filter data system, item, gui --- .../features/custom/blocks/CustomBlocks.kt | 2 + .../custom/blocks/filter/CustomFilterBlock.kt | 52 ++++++ .../custom/blocks/filter/ItemFilterBlock.kt | 45 +++++ .../custom/items/CustomItemRegistry.kt | 1 + .../ion/server/features/gui/GuiWrapper.kt | 5 + .../gui/custom/filter/ItemFilterGui.kt | 167 ++++++++++++++++++ .../gui/interactable/InteractableGUI.kt | 45 +++-- .../features/transport/filters/FilterData.kt | 37 ++-- .../filters/{FilterKey.kt => FilterEntry.kt} | 19 +- .../features/transport/filters/FilterType.kt | 56 +++++- .../filters/manager/ChunkFilterManager.kt | 13 ++ .../filters/manager/FilterManager.kt | 79 +++++++++ .../filters/manager/ShipFilterManager.kt | 13 ++ .../fluids/FluidPersistentDataType.kt | 2 +- .../manager/ChunkTransportManager.kt | 3 + .../transport/manager/ShipTransportManager.kt | 3 + .../transport/manager/TransportManager.kt | 2 + .../extractors/ChunkExtractorManager.kt | 4 +- .../persistence/PDCSerializers.kt | 2 + .../ion/server/miscellaneous/utils/Items.kt | 3 + 20 files changed, 508 insertions(+), 45 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiWrapper.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/{FilterKey.kt => FilterEntry.kt} (56%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ShipFilterManager.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 5b0914cf24..c5939698b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.custom.blocks import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import net.horizonsend.ion.server.features.custom.blocks.extractor.AdvancedItemExtractorBlock +import net.horizonsend.ion.server.features.custom.blocks.filter.ItemFilterBlock import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC @@ -207,6 +208,7 @@ object CustomBlocks { val MULTIBLOCK_WORKBENCH = register(MultiblockWorkbench) val ADVANCED_ITEM_EXTRACTOR = register(AdvancedItemExtractorBlock) + val ITEM_FILTER = register(ItemFilterBlock) fun customItemDrop(identifier: String, amount: Int = 1): Supplier> { val customItem = CustomItemRegistry.getByIdentifier(identifier)?.constructItemStack() ?: return Supplier { listOf() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt new file mode 100644 index 0000000000..3bd671aa01 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -0,0 +1,52 @@ +package net.horizonsend.ion.server.features.custom.blocks.filter + +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock +import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem +import net.horizonsend.ion.server.features.gui.GuiWrapper +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown +import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.block.Block +import org.bukkit.block.CommandBlock +import org.bukkit.block.data.BlockData +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import java.util.function.Supplier + +abstract class CustomFilterBlock>( + identifier: String, + blockData: BlockData, + drops: BlockLoot, + customBlockItem: Supplier +) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { + val cooldown = PerPlayerCooldown(5L) + + override fun onRightClick(event: PlayerInteractEvent, block: Block) { + event.isCancelled = true + event.player.closeInventory() + + val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return + + val key = toBlockKey(block.x, block.y, block.z) + + val filterManager = chunk.transportNetwork.filterManager + val filterData = filterManager.getFilter(key) ?: filterManager.registerFilter(key, this) + + cooldown.tryExec(event.player) { + Tasks.sync { + @Suppress("UNCHECKED_CAST") + val gui = getGui(event.player, block, filterData as D) { block.state as CommandBlock } + + gui.open() + } + } + } + + abstract fun createData(pos: BlockKey): D + + abstract fun getGui(player: Player, block: Block, filterData: D, commandBlock: Supplier) : GuiWrapper +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt new file mode 100644 index 0000000000..6fc4eb0973 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -0,0 +1,45 @@ +package net.horizonsend.ion.server.features.custom.blocks.filter + +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry +import net.horizonsend.ion.server.features.gui.GuiWrapper +import net.horizonsend.ion.server.features.gui.custom.filter.ItemFilterGui +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Material +import org.bukkit.block.Block +import org.bukkit.block.BlockFace +import org.bukkit.block.CommandBlock +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack +import java.util.function.Supplier + +object ItemFilterBlock : CustomFilterBlock>( + identifier = "ITEM_FILTER", + blockData = Material.COMMAND_BLOCK.createBlockData { t -> + t as org.bukkit.block.data.type.CommandBlock + t.facing = BlockFace.UP + t.isConditional = true + }, + drops = BlockLoot( + requiredTool = { BlockLoot.Tool.PICKAXE }, + drops = customItemDrop(CustomItemRegistry::ITEM_FILTER) + ), + customBlockItem = CustomItemRegistry::ITEM_FILTER, + +) { + override fun createData(pos: BlockKey): FilterData { + return FilterData(pos, FilterType.ItemType) + } + + override fun getGui( + player: Player, + block: Block, + filterData: FilterData, + commandBlock: Supplier + ): GuiWrapper { + return ItemFilterGui(player, filterData, commandBlock) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index 0141c18175..35f25e6d39 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -330,6 +330,7 @@ object CustomItemRegistry : IonServerComponent() { val WRENCH = register(Wrench) val ADVANCED_ITEM_EXTRACTOR = customBlockItem("ADVANCED_ITEM_EXTRACTOR", "tool/multiblock_workbench", text("Advanced Item Extractor"), CustomBlocks::ADVANCED_ITEM_EXTRACTOR) + val ITEM_FILTER = customBlockItem("ITEM_FILTER", "tool/multiblock_workbench", text("Item Filter"), CustomBlocks::ITEM_FILTER) private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( text("$tierName ", tierColor), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiWrapper.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiWrapper.kt new file mode 100644 index 0000000000..66e84253fd --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiWrapper.kt @@ -0,0 +1,5 @@ +package net.horizonsend.ion.server.features.gui + +interface GuiWrapper { + fun open() +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt new file mode 100644 index 0000000000..47fef32139 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -0,0 +1,167 @@ +package net.horizonsend.ion.server.features.gui.custom.filter + +import io.papermc.paper.datacomponent.DataComponentTypes +import io.papermc.paper.datacomponent.item.ItemAttributeModifiers +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.features.gui.GuiItem +import net.horizonsend.ion.server.features.gui.GuiItems.createButton +import net.horizonsend.ion.server.features.gui.GuiText +import net.horizonsend.ion.server.features.gui.GuiWrapper +import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI.Companion.setTitle +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterEntry +import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.features.transport.filters.manager.FilterManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.updateData +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updateLore +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import org.bukkit.block.CommandBlock +import org.bukkit.entity.Player +import org.bukkit.event.inventory.ClickType +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.inventory.InventoryView +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType +import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper +import xyz.xenondevs.invui.gui.Gui +import xyz.xenondevs.invui.item.ItemProvider +import xyz.xenondevs.invui.item.impl.AbstractItem +import xyz.xenondevs.invui.window.Window +import java.util.function.Supplier + +var strictess = mutableMapOf() + +class ItemFilterGui(val viewer: Player, private val data: FilterData, private val commandBlock: Supplier) : GuiWrapper { + private var currentWindow: Window? = null + + val whitelistText get() = if (data.isWhitelist) text("Whitelist") else text("Blacklist") + + val toggleWhitelistButton = createButton(GuiItem.CRUISER.makeItem(whitelistText)) { _, _, event -> + data.isWhitelist = !data.isWhitelist + setSlotOverlay(event.view) + } + + override fun open() { + val gui = Gui.normal() + .setStructure( + "1 2 3 4 5 6 x z x", + "a b c d e f x x x", + ) + .addIngredient('z', toggleWhitelistButton) + + @Suppress("UNCHECKED_CAST") + val filterEntries = data.entries.take(6).toMutableList() as MutableList> + + // Pad list + if (filterEntries.size < 6) repeat(6 - filterEntries.size) { + filterEntries.add(FilterEntry(null, FilterType.ItemType)) + } + + data.entries = filterEntries + + for (slot in data.entries.indices) { + val entry = data.entries[slot] as FilterEntry + gui.addIngredient('1' + slot, filterSlotProvider(entry, slot)) + gui.addIngredient('a' + slot, strictnessSlotProvider(entry, slot)) + } + + val window = Window + .single() + .setGui(gui) + .setTitle(AdventureComponentWrapper(getSlotOverlay())) + .addCloseHandler { + FilterManager.save(commandBlock.get(), data) + } + .build(viewer) + + currentWindow = window.apply { open() } + } + + fun filterSlotProvider(entry: FilterEntry, slot: Int) = object : AbstractItem() { + override fun handleClick(clickType: ClickType, player: Player, event: InventoryClickEvent) { + val cursor = event.cursor + + if (cursor.isEmpty) { + entry.value = null + } else { + entry.value = cursor + } + + notifyWindows() + setSlotOverlay(event.view) + + @Suppress("UNCHECKED_CAST") + (data.entries as MutableList>).set(slot, entry) + FilterManager.save(commandBlock.get(), data) + } + + override fun getItemProvider(viewer: Player?): ItemProvider = ItemProvider { + (data.type as FilterType.ItemType).toItem(data.type.cast(entry)) ?: ItemStack.empty() + } + } + + fun strictnessSlotProvider(entry: FilterEntry, slot: Int) = object : AbstractItem() { + override fun handleClick(clickType: ClickType, player: Player, event: InventoryClickEvent) { + strictess[slot] = !(strictess.getOrDefault(slot, true)) + + notifyWindows() + setSlotOverlay(event.view) + + @Suppress("UNCHECKED_CAST") + (data.entries as MutableList>).set(slot, entry) + FilterManager.save(commandBlock.get(), data) + } + + override fun getItemProvider(viewer: Player?): ItemProvider = ItemProvider { + getStrictnessItem(strictess.getOrDefault(slot, true)) + } + } + + fun getStrictnessItem(strict: Boolean): ItemStack { + val base = POWER_DRILL_BASIC.constructItemStack().updatePersistentDataContainer { + set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, "USELESS") + } + + base.updateData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP, true) + base.updateData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().build()) + + if (strict) { + POWER_DRILL_BASIC.getComponent(CustomComponentTypes.POWER_STORAGE).setPower(POWER_DRILL_BASIC, base, 25000) + base.updateDisplayName(text("Strict item checks")) + base.updateLore(mutableListOf( + text("All item data will be matched.") + )) + + return base + } + + base.updateDisplayName(text("Loose item checks")) + base.updateLore(mutableListOf( + text("Only item IDs will be matched.") + )) + + return base + } + + fun getSlotOverlay(): Component = GuiText("Item Filter") + .setSlotOverlay( + ". . . . . . # # #", + "# # # # # # # # #", + ) + .add( + component = whitelistText, + alignment = GuiText.TextAlignment.CENTER, + horizontalShift = 55, + verticalShift = 20 + ) + .build() + + fun setSlotOverlay(view: InventoryView) { + view.setTitle(getSlotOverlay()) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt index 0bc0348c27..8aa4603031 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/interactable/InteractableGUI.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.gui.interactable import io.papermc.paper.adventure.PaperAdventure +import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.nations.gui.playerClicker import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.minecraft @@ -24,7 +25,7 @@ import org.bukkit.inventory.ItemStack import java.util.UUID import java.util.function.Consumer -abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { +abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder, GuiWrapper { protected abstract val internalInventory: Inventory abstract val inventorySize: Int @@ -36,7 +37,7 @@ abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { protected val noDropSlots: MutableSet = mutableSetOf() protected val lockedSlots: MutableSet = mutableSetOf() - fun open() { + override fun open() { // Will return CRAFTING if none is open if (viewer.openInventory.type != InventoryType.CRAFTING && viewer.openInventory.type != InventoryType.CREATIVE) return @@ -60,6 +61,17 @@ abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { abstract fun canRemove(slot: Int, player: Player): Boolean abstract fun itemChanged(changedSlot: Int, changedItem: ItemStack) + open fun handleAddItem(slot: Int, item: ItemStack, event: InventoryClickEvent) { + buttons[slot]?.accept(event) + + if (lockedSlots.contains(slot) || !canAdd(item, slot, event.whoClicked as Player)) { + event.isCancelled = true + return + } + + itemChanged(slot, item) + } + open fun handleAddItem(slot: Int, item: ItemStack, event: InventoryInteractEvent) { if (lockedSlots.contains(slot) || !canAdd(item, slot, event.whoClicked as Player)) { event.isCancelled = true @@ -161,7 +173,14 @@ abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { private val inventories = mutableMapOf() fun getInventory(uuid: UUID): InteractableGUI? = inventories[uuid] - fun setInventory(uuid: UUID, gui: InteractableGUI) { inventories[uuid] = gui } + fun setInventory(uuid: UUID, gui: InteractableGUI?) { + if (gui == null) { + inventories.remove(uuid) + return + } + + inventories[uuid] = gui + } @EventHandler fun onInventoryClick(event: InventoryClickEvent) { @@ -204,17 +223,17 @@ abstract class InteractableGUI(protected val viewer: Player) : InventoryHolder { holder.handleClose(event) } } - } - /** - * Updates the title of this inventory - **/ - protected fun InventoryView.setTitle(title: Component) { - val entityPlayer = (player as Player).minecraft - val containerId = entityPlayer.containerMenu.containerId - val windowType = CraftContainer.getNotchInventoryType(topInventory) - entityPlayer.connection.send(ClientboundOpenScreenPacket(containerId, windowType, PaperAdventure.asVanilla(title))) - (player as Player).updateInventory() + /** + * Updates the title of this inventory + **/ + fun InventoryView.setTitle(title: Component) { + val entityPlayer = (player as Player).minecraft + val containerId = entityPlayer.containerMenu.containerId + val windowType = CraftContainer.getNotchInventoryType(topInventory) + entityPlayer.connection.send(ClientboundOpenScreenPacket(containerId, windowType, PaperAdventure.asVanilla(title))) + (player as Player).updateInventory() + } } /** diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt index 6e88f60ba9..0365b41dda 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -1,34 +1,43 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class FilterData( - val isWhitelist: Boolean, - val entries: MutableList> +data class FilterData( + var position: BlockKey, + val type: FilterType, + var entries: MutableList> = mutableListOf(), + var isWhitelist: Boolean = true, ) { - companion object : PersistentDataType> { - override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - override fun getComplexType(): Class> = FilterData::class.java - + companion object FilterDataSerializer : PDCSerializers.RegisteredSerializer>("FILTER_DATA", FilterData::class) { override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*> { val whitelist = primitive.getOrDefault(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, true) - val entries = primitive.getOrDefault(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, arrayOf()) - val formatted = entries.mapTo(mutableListOf()) { entry -> - FilterKey.fromPrimitive(entry, context) - } + val entries = primitive.getOrDefault(NamespacedKeys.FILTER_ENTRY, PersistentDataType.LIST.dataContainers(), listOf()) + + val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! + + val filterType = FilterType[filterTypeIdentifier] + val formatted = filterType.loadFilterEntries(entries, context) - return FilterData(whitelist, formatted) + return FilterData( + position = primitive.get(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG)!!, + type = filterType, + entries = formatted, + isWhitelist = whitelist + ) } override fun toPrimitive(complex: FilterData<*>, context: PersistentDataAdapterContext): PersistentDataContainer { val data = context.newPersistentDataContainer() + data.set(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG, complex.position) data.set(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, complex.isWhitelist) - val array = Array(complex.entries.size) { FilterKey.toPrimitive(complex.entries[it], context) } - data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.TAG_CONTAINER_ARRAY, array) + data.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, complex.type.javaClass.simpleName) + data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.LIST.dataContainers(), complex.entries.map { key -> FilterEntry.toPrimitive(key, context) }) return data } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt similarity index 56% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt index f8639b1217..e81950038c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterKey.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt @@ -5,26 +5,29 @@ import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -class FilterKey(val entry: T, val type: FilterType) { - companion object : PersistentDataType> { - override fun getComplexType(): Class> = FilterKey::class.java +data class FilterEntry(var value: T?, val type: FilterType, /*TODO configuration*/) { + companion object : PersistentDataType> { + override fun getComplexType(): Class> = FilterEntry::class.java override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterKey<*> { + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterEntry<*> { val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! - val filterType = FilterType.filterTypes[filterTypeIdentifier]!! + val filterType = FilterType[filterTypeIdentifier] - return FilterKey(filterType.retrieve(primitive)!!, filterType) + return FilterEntry(filterType.retrieve(primitive), filterType) } - override fun toPrimitive(complex: FilterKey<*>, context: PersistentDataAdapterContext): PersistentDataContainer { + override fun toPrimitive(complex: FilterEntry<*>, context: PersistentDataAdapterContext): PersistentDataContainer { val pdc = context.newPersistentDataContainer() val typeIdentifier = complex.type.javaClass.simpleName pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) - complex.type.store(pdc, complex.entry) + complex.value?.let { complex.type.store(pdc, it) } return pdc } + + @Suppress("UNCHECKED_CAST") + inline fun empty() = FilterEntry(null, FilterType[T::class] as FilterType) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index df443dd522..720f85fb78 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -1,20 +1,27 @@ package net.horizonsend.ion.server.features.transport.filters import com.manya.pdc.minecraft.ItemStackDataType +import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updateLore +import org.bukkit.Material import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType +import kotlin.reflect.KClass -abstract class FilterType(val cacheType: CacheType, val typeClass: Class, val persistentDataType: PersistentDataType<*, T>) { - data object FluidType : FilterType(CacheType.FLUID, Fluid::class.java, FluidPersistentDataType) - data object ItemType : FilterType(CacheType.ITEMS, ItemStack::class.java, ItemStackDataType()) - +abstract class FilterType(val cacheType: CacheType, val identifier: String, val typeClass: Class, val persistentDataType: PersistentDataType<*, T>) { fun store(pdc: PersistentDataContainer, data: Any) { if (!typeClass.isInstance(data)) return + if (data is ItemStack && data.isEmpty) { + return + } + @Suppress("UNCHECKED_CAST") pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, data as T) } @@ -23,10 +30,43 @@ abstract class FilterType(val cacheType: CacheType, val typeClass: Clas return pdc.get(NamespacedKeys.FILTER_ENTRY, persistentDataType) } + fun loadFilterEntries( + primitive: List, + context: PersistentDataAdapterContext + ): MutableList> { + return primitive.mapTo(mutableListOf()) { entry -> + @Suppress("UNCHECKED_CAST") + FilterEntry.fromPrimitive(entry, context) as FilterEntry + } + } + + @Suppress("UNCHECKED_CAST") + fun cast(entry: FilterEntry<*>): FilterEntry = entry as FilterEntry + + abstract fun toItem(entry: FilterEntry): ItemStack? + + data object FluidType : FilterType(CacheType.FLUID, "FLUID", Fluid::class.java, FluidPersistentDataType) { + override fun toItem(entry: FilterEntry): ItemStack? { + val value = entry.value + if (value == null) return null + + return ItemStack(Material.WARPED_FUNGUS_ON_A_STICK) + .updateDisplayName(value.displayName) + .updateLore(value.categories.map { it.toComponent() }) + } + } + + data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemStackDataType()) { + override fun toItem(entry: FilterEntry): ItemStack? = entry.value?.clone() + } + companion object { - val filterTypes = mutableMapOf>( - FluidType.javaClass.simpleName to FluidType, - ItemType.javaClass.simpleName to ItemType, - ) + private val byId = mapOf("FLUID" to FluidType, "ITEMS" to ItemType) + + operator fun get(identifier: String): FilterType<*> = byId[identifier]!! + + private val byClass: Map, FilterType<*>> = mapOf(Fluid::class to FluidType, ItemStack::class to ItemType) + + operator fun get(clazz: KClass<*>): FilterType<*> = byClass[clazz]!! } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt new file mode 100644 index 0000000000..4d045a3874 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.transport.filters.manager + +import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager + +class ChunkFilterManager(manager: ChunkTransportManager) : FilterManager(manager) { + override fun save() { + TODO("Not yet implemented") + } + + override fun load() { + TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt new file mode 100644 index 0000000000..df58142e06 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -0,0 +1,79 @@ +package net.horizonsend.ion.server.features.transport.filters.manager + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import net.horizonsend.ion.server.features.custom.blocks.filter.CustomFilterBlock +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.features.transport.manager.TransportManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.NbtUtils +import net.minecraft.server.MinecraftServer +import org.bukkit.Material +import org.bukkit.block.CommandBlock +import org.bukkit.craftbukkit.inventory.CraftItemStack +import org.bukkit.inventory.ItemStack + +abstract class FilterManager(val manager: TransportManager<*>) { + val filters = Long2ObjectOpenHashMap>() + + private val mutex = Any() + + fun getFilters(): Collection> { + return filters.values + } + + fun getFilters(type: FilterType): Collection> { + return filters.values + .filter { data -> data.type == type } + .filterIsInstance>() + } + + fun getFilter(key: BlockKey): FilterData<*>? { + return filters[key] + } + + fun addFilter(key: BlockKey, data: FilterData<*>) { + val local = manager.getLocalCoordinate(toVec3i(key)) + + synchronized(mutex) { + filters[toBlockKey(local)] = data + } + } + + fun > registerFilter(key: BlockKey, block: CustomFilterBlock): D { + val data = block.createData(key) + + addFilter(key, data) + + return data + } + + fun removeFilter(key: BlockKey) = synchronized(mutex) { + val local = manager.getLocalCoordinate(toVec3i(key)) + } + + fun isFilterPresent(key: BlockKey): Boolean = synchronized(mutex) { + return filters.containsKey(key) + } + + abstract fun save() + abstract fun load() + + companion object { + fun save(commandBlock: CommandBlock, data: FilterData<*>) { + val test = ItemStack(Material.DIRT).updatePersistentDataContainer { + set(NamespacedKeys.FILTER_DATA, FilterData, data) + } + + println(NbtUtils.structureToSnbt(CraftItemStack.asNMSCopy(test).save(MinecraftServer.getServer().registryAccess()) as CompoundTag)) + + commandBlock.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, data) + commandBlock.update() + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ShipFilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ShipFilterManager.kt new file mode 100644 index 0000000000..eed5c65644 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ShipFilterManager.kt @@ -0,0 +1,13 @@ +package net.horizonsend.ion.server.features.transport.filters.manager + +import net.horizonsend.ion.server.features.transport.manager.ShipTransportManager + +class ShipFilterManager(manager: ShipTransportManager) : FilterManager(manager) { + override fun save() { + TODO("Not yet implemented") + } + + override fun load() { + TODO("Not yet implemented") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt index eda60f3345..01a8ef2524 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/fluids/FluidPersistentDataType.kt @@ -8,7 +8,7 @@ object FluidPersistentDataType : PersistentDataType { override fun getPrimitiveType(): Class = String::class.java override fun fromPrimitive(primitive: String, context: PersistentDataAdapterContext): Fluid { - return FluidRegistry.get(primitive)!! + return FluidRegistry[primitive]!! } override fun toPrimitive(complex: Fluid, context: PersistentDataAdapterContext): String { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 798196f14e..8981dce020 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.filters.manager.ChunkFilterManager +import net.horizonsend.ion.server.features.transport.filters.manager.FilterManager import net.horizonsend.ion.server.features.transport.manager.extractors.ChunkExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ChunkCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache @@ -15,6 +17,7 @@ import org.bukkit.block.Block class ChunkTransportManager(val chunk: IonChunk) : TransportManager>() { override val extractorManager: ChunkExtractorManager = ChunkExtractorManager(this) + override val filterManager: FilterManager = ChunkFilterManager(this) override val powerNodeManager = ChunkCacheHolder(this) { PowerTransportCache(it) } override val solarPanelManager = ChunkCacheHolder(this) { SolarPanelCache(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt index 0e4b7b39a3..56f9376f5c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ShipTransportManager.kt @@ -3,6 +3,8 @@ package net.horizonsend.ion.server.features.transport.manager import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.filters.manager.FilterManager +import net.horizonsend.ion.server.features.transport.filters.manager.ShipFilterManager import net.horizonsend.ion.server.features.transport.manager.extractors.ShipExtractorManager import net.horizonsend.ion.server.features.transport.manager.holders.ShipCacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache @@ -14,6 +16,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i class ShipTransportManager(val starship: Starship) : TransportManager>() { override val extractorManager: ShipExtractorManager = ShipExtractorManager(this) + override val filterManager: FilterManager = ShipFilterManager(this) val inputManager = ShipInputManager(this) override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 0a080d1d45..84b280beea 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.manager +import net.horizonsend.ion.server.features.transport.filters.manager.FilterManager import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.data.AdvancedExtractorData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder @@ -11,6 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i abstract class TransportManager> { abstract val extractorManager: ExtractorManager + abstract val filterManager: FilterManager abstract val powerNodeManager: CacheHolder abstract val solarPanelManager: CacheHolder diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 7b5fe1d19e..50e90c2aed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -54,7 +54,9 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag override fun removeExtractor(key: BlockKey): ExtractorData? = synchronized(mutex) { needsSave = true - return extractors.remove(key) + return synchronized(mutex) { + extractors.remove(key) + } } override fun isExtractorPresent(key: BlockKey): Boolean = synchronized(mutex) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt index 88f79d6c8b..4e1e2907b6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.miscellaneous.registrations.persistence +import net.horizonsend.ion.server.features.transport.filters.FilterData.FilterDataSerializer import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer @@ -17,6 +18,7 @@ object PDCSerializers { } val ITEM_EXTRACTOR_METADATA = register(ItemExtractorData.ItemExtractorMetaData.Companion) + val FILTER_DATA = register(FilterDataSerializer) operator fun get(identifier: String) : RegisteredSerializer<*> = registeredSerializers[identifier]!! diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt index bcc5bd5e4a..274e3ab9cc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt @@ -28,6 +28,9 @@ fun ItemStack.updateMeta(block: (ItemMeta) -> Unit): ItemStack = apply { fun ItemStack.updatePersistentDataContainer(edit: PersistentDataContainer.() -> Unit) = updateMeta { meta -> edit.invoke(meta.persistentDataContainer) } fun ItemStack.updateData(type: DataComponentType.Valued, data: T): ItemStack = apply { setData(type, data) } +fun ItemStack.updateData(type: DataComponentType.NonValued, value: Boolean): ItemStack = apply { + if (value) setData(type) else unsetData(type) +} fun ItemStack.setModel(model: Key) = updateData(DataComponentTypes.ITEM_MODEL, model) fun ItemStack.setModel(model: String) = updateData(DataComponentTypes.ITEM_MODEL, NamespacedKeys.packKey(model)) From 4cf6b57c46eccb8ace78e3928e5b1161cf807600 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:52:05 -0600 Subject: [PATCH 429/500] change item serialization method --- .../gui/custom/filter/ItemFilterGui.kt | 58 +++++++++---------- .../features/transport/filters/FilterData.kt | 5 ++ .../features/transport/filters/FilterType.kt | 3 +- .../transport/filters/ItemSerializer.kt | 32 ++++++++++ .../filters/manager/FilterManager.kt | 21 +++---- 5 files changed, 76 insertions(+), 43 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt index 47fef32139..6452171ffa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -43,7 +43,7 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, val toggleWhitelistButton = createButton(GuiItem.CRUISER.makeItem(whitelistText)) { _, _, event -> data.isWhitelist = !data.isWhitelist - setSlotOverlay(event.view) + updateSlotOverlay(event.view) } override fun open() { @@ -74,14 +74,28 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, .single() .setGui(gui) .setTitle(AdventureComponentWrapper(getSlotOverlay())) - .addCloseHandler { - FilterManager.save(commandBlock.get(), data) - } .build(viewer) currentWindow = window.apply { open() } } + fun getSlotOverlay(): Component = GuiText("Item Filter") + .setSlotOverlay( + ". . . . . . # # #", + "# # # # # # # # #", + ) + .add( + component = whitelistText, + alignment = GuiText.TextAlignment.CENTER, + horizontalShift = 55, + verticalShift = 20 + ) + .build() + + fun updateSlotOverlay(view: InventoryView) { + view.setTitle(getSlotOverlay()) + } + fun filterSlotProvider(entry: FilterEntry, slot: Int) = object : AbstractItem() { override fun handleClick(clickType: ClickType, player: Player, event: InventoryClickEvent) { val cursor = event.cursor @@ -92,15 +106,19 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, entry.value = cursor } + println("updated entry to: ${entry.value}, ${System.identityHashCode(entry)}") + notifyWindows() - setSlotOverlay(event.view) + updateSlotOverlay(event.view) @Suppress("UNCHECKED_CAST") - (data.entries as MutableList>).set(slot, entry) + (data.entries as MutableList>)[slot] = entry FilterManager.save(commandBlock.get(), data) } - override fun getItemProvider(viewer: Player?): ItemProvider = ItemProvider { + override fun getItemProvider(viewer: Player): ItemProvider = provider + val provider = ItemProvider { + (data.type as FilterType.ItemType).toItem(data.type.cast(entry)) ?: ItemStack.empty() } } @@ -110,16 +128,15 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, strictess[slot] = !(strictess.getOrDefault(slot, true)) notifyWindows() - setSlotOverlay(event.view) + updateSlotOverlay(event.view) @Suppress("UNCHECKED_CAST") - (data.entries as MutableList>).set(slot, entry) + (data.entries as MutableList>)[slot] = entry FilterManager.save(commandBlock.get(), data) } - override fun getItemProvider(viewer: Player?): ItemProvider = ItemProvider { - getStrictnessItem(strictess.getOrDefault(slot, true)) - } + override fun getItemProvider(viewer: Player): ItemProvider = provider + val provider = ItemProvider { getStrictnessItem(strictess.getOrDefault(slot, true)) } } fun getStrictnessItem(strict: Boolean): ItemStack { @@ -147,21 +164,4 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, return base } - - fun getSlotOverlay(): Component = GuiText("Item Filter") - .setSlotOverlay( - ". . . . . . # # #", - "# # # # # # # # #", - ) - .add( - component = whitelistText, - alignment = GuiText.TextAlignment.CENTER, - horizontalShift = 55, - verticalShift = 20 - ) - .build() - - fun setSlotOverlay(view: InventoryView) { - view.setTitle(getSlotOverlay()) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt index 0365b41dda..367351d2bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -37,6 +37,11 @@ data class FilterData( data.set(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG, complex.position) data.set(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, complex.isWhitelist) data.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, complex.type.javaClass.simpleName) +// +// println("Serialized entries") +// Throwable().printStackTrace() +// println(complex.entries.map { key -> NbtUtils.structureToSnbt((FilterEntry.toPrimitive(key, context) as CraftPersistentDataContainer).toTagCompound()) }) + data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.LIST.dataContainers(), complex.entries.map { key -> FilterEntry.toPrimitive(key, context) }) return data diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index 720f85fb78..1124b6bef3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.filters -import com.manya.pdc.minecraft.ItemStackDataType import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType @@ -56,7 +55,7 @@ abstract class FilterType(val cacheType: CacheType, val identifier: Str } } - data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemStackDataType()) { + data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemSerializer) { override fun toItem(entry: FilterEntry): ItemStack? = entry.value?.clone() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt new file mode 100644 index 0000000000..bc3adc32be --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt @@ -0,0 +1,32 @@ +package net.horizonsend.ion.server.features.transport.filters + +import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import net.minecraft.nbt.CompoundTag +import net.minecraft.server.MinecraftServer +import net.minecraft.world.item.ItemStack as NMSItemStack +import org.bukkit.craftbukkit.inventory.CraftItemStack +import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer +import org.bukkit.inventory.ItemStack as BukkitItemStack +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType + +object ItemSerializer : PersistentDataType { + override fun getPrimitiveType(): Class = PersistentDataContainer::class.java + override fun getComplexType(): Class = BukkitItemStack::class.java + + override fun toPrimitive(complex: BukkitItemStack, context: PersistentDataAdapterContext): PersistentDataContainer { + val compound = CraftItemStack.asNMSCopy(complex).saveOptional(MinecraftServer.getServer().registryAccess()) as CompoundTag + + return CraftPersistentDataContainer( + compound.allKeys.associateWithNotNull(compound::get), + (context.newPersistentDataContainer() as CraftPersistentDataContainer).dataTagTypeRegistry + ) + } + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): BukkitItemStack { + val raw = (primitive as CraftPersistentDataContainer).toTagCompound() + val nms = NMSItemStack.parseOptional(MinecraftServer.getServer().registryAccess(), raw) + return CraftItemStack.asBukkitCopy(nms) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt index df58142e06..c6b20181af 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -9,14 +9,7 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.NbtUtils -import net.minecraft.server.MinecraftServer -import org.bukkit.Material import org.bukkit.block.CommandBlock -import org.bukkit.craftbukkit.inventory.CraftItemStack -import org.bukkit.inventory.ItemStack abstract class FilterManager(val manager: TransportManager<*>) { val filters = Long2ObjectOpenHashMap>() @@ -66,11 +59,15 @@ abstract class FilterManager(val manager: TransportManager<*>) { companion object { fun save(commandBlock: CommandBlock, data: FilterData<*>) { - val test = ItemStack(Material.DIRT).updatePersistentDataContainer { - set(NamespacedKeys.FILTER_DATA, FilterData, data) - } - - println(NbtUtils.structureToSnbt(CraftItemStack.asNMSCopy(test).save(MinecraftServer.getServer().registryAccess()) as CompoundTag)) +// val test = ItemStack(Material.DIRT).updatePersistentDataContainer { +// set(NamespacedKeys.FILTER_DATA, FilterData, data) +// } +// +// for (entry in data.entries) { +// println("${entry.value}, ${System.identityHashCode(entry)}") +// } +// +// println(NbtUtils.structureToSnbt(CraftItemStack.asNMSCopy(test).save(MinecraftServer.getServer().registryAccess()) as CompoundTag)) commandBlock.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, data) commandBlock.update() From ac53bd64bd879d06c6cf30093d77a87876f1c298 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 24 Jan 2025 13:56:06 -0600 Subject: [PATCH 430/500] fix saving, retrieve data from state --- .../gui/custom/filter/ItemFilterGui.kt | 5 +---- .../features/transport/filters/FilterData.kt | 6 +----- .../features/transport/filters/FilterEntry.kt | 2 +- .../features/transport/filters/FilterType.kt | 4 ++-- .../transport/filters/ItemSerializer.kt | 13 ++++--------- .../transport/filters/manager/FilterManager.kt | 18 +++++++----------- .../transport/manager/ChunkTransportManager.kt | 5 +++++ .../transport/manager/ShipTransportManager.kt | 3 +++ .../transport/manager/TransportManager.kt | 3 +++ 9 files changed, 27 insertions(+), 32 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt index 6452171ffa..3a6bc40712 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -103,11 +103,9 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, if (cursor.isEmpty) { entry.value = null } else { - entry.value = cursor + entry.value = cursor.clone() } - println("updated entry to: ${entry.value}, ${System.identityHashCode(entry)}") - notifyWindows() updateSlotOverlay(event.view) @@ -118,7 +116,6 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, override fun getItemProvider(viewer: Player): ItemProvider = provider val provider = ItemProvider { - (data.type as FilterType.ItemType).toItem(data.type.cast(entry)) ?: ItemStack.empty() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt index 367351d2bd..412e837b1b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -36,11 +36,7 @@ data class FilterData( data.set(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG, complex.position) data.set(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, complex.isWhitelist) - data.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, complex.type.javaClass.simpleName) -// -// println("Serialized entries") -// Throwable().printStackTrace() -// println(complex.entries.map { key -> NbtUtils.structureToSnbt((FilterEntry.toPrimitive(key, context) as CraftPersistentDataContainer).toTagCompound()) }) + data.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, complex.type.identifier) data.set(NamespacedKeys.FILTER_ENTRY, PersistentDataType.LIST.dataContainers(), complex.entries.map { key -> FilterEntry.toPrimitive(key, context) }) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt index e81950038c..4208faed11 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt @@ -19,7 +19,7 @@ data class FilterEntry(var value: T?, val type: FilterType, /*TO override fun toPrimitive(complex: FilterEntry<*>, context: PersistentDataAdapterContext): PersistentDataContainer { val pdc = context.newPersistentDataContainer() - val typeIdentifier = complex.type.javaClass.simpleName + val typeIdentifier = complex.type.identifier pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) complex.value?.let { complex.type.store(pdc, it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index 1124b6bef3..c043cf84c0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -62,10 +62,10 @@ abstract class FilterType(val cacheType: CacheType, val identifier: Str companion object { private val byId = mapOf("FLUID" to FluidType, "ITEMS" to ItemType) - operator fun get(identifier: String): FilterType<*> = byId[identifier]!! + operator fun get(identifier: String): FilterType<*> = byId[identifier] ?: throw NoSuchElementException("Filter type $identifier not found") private val byClass: Map, FilterType<*>> = mapOf(Fluid::class to FluidType, ItemStack::class to ItemType) - operator fun get(clazz: KClass<*>): FilterType<*> = byClass[clazz]!! + operator fun get(clazz: KClass<*>): FilterType<*> = byClass[clazz] ?: throw NoSuchElementException("Filter type for ${clazz.simpleName} not found") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt index bc3adc32be..6207e03fc3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/ItemSerializer.kt @@ -1,11 +1,10 @@ package net.horizonsend.ion.server.features.transport.filters -import net.horizonsend.ion.server.miscellaneous.utils.associateWithNotNull +import net.horizonsend.ion.server.features.space.data.CompoundTagType import net.minecraft.nbt.CompoundTag import net.minecraft.server.MinecraftServer import net.minecraft.world.item.ItemStack as NMSItemStack import org.bukkit.craftbukkit.inventory.CraftItemStack -import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer import org.bukkit.inventory.ItemStack as BukkitItemStack import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer @@ -17,16 +16,12 @@ object ItemSerializer : PersistentDataType) { } fun > registerFilter(key: BlockKey, block: CustomFilterBlock): D { - val data = block.createData(key) + val global = manager.getGlobalCoordinate(toVec3i(key)) + val world = manager.getWorld() + + val state = world.getBlockState(global.x, global.y, global.z) as? CommandBlock + + @Suppress("UNCHECKED_CAST") + val data = state?.persistentDataContainer?.get(NamespacedKeys.FILTER_DATA, FilterData) as? D ?: block.createData(key) addFilter(key, data) @@ -59,16 +65,6 @@ abstract class FilterManager(val manager: TransportManager<*>) { companion object { fun save(commandBlock: CommandBlock, data: FilterData<*>) { -// val test = ItemStack(Material.DIRT).updatePersistentDataContainer { -// set(NamespacedKeys.FILTER_DATA, FilterData, data) -// } -// -// for (entry in data.entries) { -// println("${entry.value}, ${System.identityHashCode(entry)}") -// } -// -// println(NbtUtils.structureToSnbt(CraftItemStack.asNMSCopy(test).save(MinecraftServer.getServer().registryAccess()) as CompoundTag)) - commandBlock.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, data) commandBlock.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt index 8981dce020..f0aca606b3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/ChunkTransportManager.kt @@ -13,6 +13,7 @@ import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.World import org.bukkit.block.Block class ChunkTransportManager(val chunk: IonChunk) : TransportManager>() { @@ -37,6 +38,10 @@ class ChunkTransportManager(val chunk: IonChunk) : TransportManager>() { override val extractorManager: ShipExtractorManager = ShipExtractorManager(this) override val filterManager: FilterManager = ShipFilterManager(this) val inputManager = ShipInputManager(this) + override fun getWorld(): World = starship.world + override val powerNodeManager = ShipCacheHolder(this) { PowerTransportCache(it) } override val solarPanelManager = ShipCacheHolder(this) { SolarPanelCache(it) } override val itemPipeManager = ShipCacheHolder(this) { ItemTransportCache(it) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt index 84b280beea..3278125869 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/TransportManager.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportC import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import org.bukkit.World abstract class TransportManager> { abstract val extractorManager: ExtractorManager @@ -34,6 +35,8 @@ abstract class TransportManager> { } } + abstract fun getWorld(): World + open fun getGlobalCoordinate(localVec3i: Vec3i): Vec3i = localVec3i open fun getLocalCoordinate(globalVec3i: Vec3i): Vec3i = globalVec3i } From 733c9e7616524e73c02850a84a2051c13a3e9f7d Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 25 Jan 2025 14:01:14 -0600 Subject: [PATCH 431/500] implement filter type specific meta data --- .../custom/blocks/filter/CustomFilterBlock.kt | 11 +-- .../custom/blocks/filter/ItemFilterBlock.kt | 9 +-- .../gui/custom/filter/ItemFilterGui.kt | 68 +++++-------------- .../features/transport/filters/FilterData.kt | 14 ++-- .../features/transport/filters/FilterEntry.kt | 30 +++++--- .../features/transport/filters/FilterMeta.kt | 30 ++++++++ .../transport/filters/FilterMethod.kt | 38 +++++++++++ .../features/transport/filters/FilterType.kt | 49 +++++++++---- .../filters/manager/FilterManager.kt | 19 +++--- .../persistence/NamespacedKeys.kt | 2 + .../persistence/PDCSerializers.kt | 3 + 11 files changed, 174 insertions(+), 99 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt index 3bd671aa01..188c2121c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -17,7 +18,7 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import java.util.function.Supplier -abstract class CustomFilterBlock>( +abstract class CustomFilterBlock( identifier: String, blockData: BlockData, drops: BlockLoot, @@ -34,19 +35,19 @@ abstract class CustomFilterBlock>( val key = toBlockKey(block.x, block.y, block.z) val filterManager = chunk.transportNetwork.filterManager - val filterData = filterManager.getFilter(key) ?: filterManager.registerFilter(key, this) + val filterData = filterManager.getFilter(key) ?: filterManager.registerFilter(key, this) cooldown.tryExec(event.player) { Tasks.sync { @Suppress("UNCHECKED_CAST") - val gui = getGui(event.player, block, filterData as D) { block.state as CommandBlock } + val gui = getGui(event.player, block, filterData as FilterData) { block.state as CommandBlock } gui.open() } } } - abstract fun createData(pos: BlockKey): D + abstract fun createData(pos: BlockKey): FilterData - abstract fun getGui(player: Player, block: Block, filterData: D, commandBlock: Supplier) : GuiWrapper + abstract fun getGui(player: Player, block: Block, filterData: FilterData, commandBlock: Supplier) : GuiWrapper } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index 6fc4eb0973..288db06c2b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -6,6 +6,7 @@ import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.gui.custom.filter.ItemFilterGui import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Material @@ -16,7 +17,7 @@ import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import java.util.function.Supplier -object ItemFilterBlock : CustomFilterBlock>( +object ItemFilterBlock : CustomFilterBlock( identifier = "ITEM_FILTER", blockData = Material.COMMAND_BLOCK.createBlockData { t -> t as org.bukkit.block.data.type.CommandBlock @@ -30,14 +31,14 @@ object ItemFilterBlock : CustomFilterBlock>( customBlockItem = CustomItemRegistry::ITEM_FILTER, ) { - override fun createData(pos: BlockKey): FilterData { - return FilterData(pos, FilterType.ItemType) + override fun createData(pos: BlockKey): FilterData { + return FilterData(pos, FilterType.ItemType) } override fun getGui( player: Player, block: Block, - filterData: FilterData, + filterData: FilterData, commandBlock: Supplier ): GuiWrapper { return ItemFilterGui(player, filterData, commandBlock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt index 3a6bc40712..f664c5b703 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -1,9 +1,5 @@ package net.horizonsend.ion.server.features.gui.custom.filter -import io.papermc.paper.datacomponent.DataComponentTypes -import io.papermc.paper.datacomponent.item.ItemAttributeModifiers -import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC -import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.gui.GuiItem import net.horizonsend.ion.server.features.gui.GuiItems.createButton import net.horizonsend.ion.server.features.gui.GuiText @@ -11,13 +7,10 @@ import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI.Companion.setTitle import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterEntry +import net.horizonsend.ion.server.features.transport.filters.FilterMeta +import net.horizonsend.ion.server.features.transport.filters.FilterMethod import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.filters.manager.FilterManager -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys -import net.horizonsend.ion.server.miscellaneous.utils.updateData -import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName -import net.horizonsend.ion.server.miscellaneous.utils.updateLore -import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import org.bukkit.block.CommandBlock @@ -26,7 +19,6 @@ import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack -import org.bukkit.persistence.PersistentDataType import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper import xyz.xenondevs.invui.gui.Gui import xyz.xenondevs.invui.item.ItemProvider @@ -34,9 +26,7 @@ import xyz.xenondevs.invui.item.impl.AbstractItem import xyz.xenondevs.invui.window.Window import java.util.function.Supplier -var strictess = mutableMapOf() - -class ItemFilterGui(val viewer: Player, private val data: FilterData, private val commandBlock: Supplier) : GuiWrapper { +class ItemFilterGui(val viewer: Player, private val data: FilterData, private val commandBlock: Supplier) : GuiWrapper { private var currentWindow: Window? = null val whitelistText get() = if (data.isWhitelist) text("Whitelist") else text("Blacklist") @@ -55,19 +45,19 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, .addIngredient('z', toggleWhitelistButton) @Suppress("UNCHECKED_CAST") - val filterEntries = data.entries.take(6).toMutableList() as MutableList> + val filterEntries = data.entries.take(6).toMutableList() as MutableList> // Pad list if (filterEntries.size < 6) repeat(6 - filterEntries.size) { - filterEntries.add(FilterEntry(null, FilterType.ItemType)) + filterEntries.add(FilterType.ItemType.buildEmptyEntry()) } data.entries = filterEntries for (slot in data.entries.indices) { - val entry = data.entries[slot] as FilterEntry - gui.addIngredient('1' + slot, filterSlotProvider(entry, slot)) - gui.addIngredient('a' + slot, strictnessSlotProvider(entry, slot)) + val entry = data.entries[slot] as FilterEntry + gui.addIngredient('1' + slot, filterSlotProvider(entry)) + gui.addIngredient('a' + slot, strictnessSlotProvider(entry)) } val window = Window @@ -96,7 +86,7 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, view.setTitle(getSlotOverlay()) } - fun filterSlotProvider(entry: FilterEntry, slot: Int) = object : AbstractItem() { + fun filterSlotProvider(entry: FilterEntry) = object : AbstractItem() { override fun handleClick(clickType: ClickType, player: Player, event: InventoryClickEvent) { val cursor = event.cursor @@ -109,8 +99,6 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, notifyWindows() updateSlotOverlay(event.view) - @Suppress("UNCHECKED_CAST") - (data.entries as MutableList>)[slot] = entry FilterManager.save(commandBlock.get(), data) } @@ -120,45 +108,21 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData, } } - fun strictnessSlotProvider(entry: FilterEntry, slot: Int) = object : AbstractItem() { + fun strictnessSlotProvider(entry: FilterEntry) = object : AbstractItem() { override fun handleClick(clickType: ClickType, player: Player, event: InventoryClickEvent) { - strictess[slot] = !(strictess.getOrDefault(slot, true)) + val currentIndex = entry.metaData.filterMethod.ordinal + val size = FilterMethod.entries.size + val nextIndex = (currentIndex + 1) % size + + entry.metaData.filterMethod = FilterMethod.entries[nextIndex] notifyWindows() updateSlotOverlay(event.view) - @Suppress("UNCHECKED_CAST") - (data.entries as MutableList>)[slot] = entry FilterManager.save(commandBlock.get(), data) } override fun getItemProvider(viewer: Player): ItemProvider = provider - val provider = ItemProvider { getStrictnessItem(strictess.getOrDefault(slot, true)) } - } - - fun getStrictnessItem(strict: Boolean): ItemStack { - val base = POWER_DRILL_BASIC.constructItemStack().updatePersistentDataContainer { - set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, "USELESS") - } - - base.updateData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP, true) - base.updateData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().build()) - - if (strict) { - POWER_DRILL_BASIC.getComponent(CustomComponentTypes.POWER_STORAGE).setPower(POWER_DRILL_BASIC, base, 25000) - base.updateDisplayName(text("Strict item checks")) - base.updateLore(mutableListOf( - text("All item data will be matched.") - )) - - return base - } - - base.updateDisplayName(text("Loose item checks")) - base.updateLore(mutableListOf( - text("Only item IDs will be matched.") - )) - - return base + val provider = ItemProvider { entry.metaData.filterMethod.icon } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt index 412e837b1b..8d13465e74 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -7,14 +7,14 @@ import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -data class FilterData( +data class FilterData( var position: BlockKey, - val type: FilterType, - var entries: MutableList> = mutableListOf(), + val type: FilterType, + var entries: MutableList> = mutableListOf(), var isWhitelist: Boolean = true, ) { - companion object FilterDataSerializer : PDCSerializers.RegisteredSerializer>("FILTER_DATA", FilterData::class) { - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*> { + companion object FilterDataSerializer : PDCSerializers.RegisteredSerializer>("FILTER_DATA", FilterData::class) { + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*, *> { val whitelist = primitive.getOrDefault(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, true) val entries = primitive.getOrDefault(NamespacedKeys.FILTER_ENTRY, PersistentDataType.LIST.dataContainers(), listOf()) @@ -23,7 +23,7 @@ data class FilterData( val filterType = FilterType[filterTypeIdentifier] val formatted = filterType.loadFilterEntries(entries, context) - return FilterData( + return FilterData( position = primitive.get(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG)!!, type = filterType, entries = formatted, @@ -31,7 +31,7 @@ data class FilterData( ) } - override fun toPrimitive(complex: FilterData<*>, context: PersistentDataAdapterContext): PersistentDataContainer { + override fun toPrimitive(complex: FilterData<*, *>, context: PersistentDataAdapterContext): PersistentDataContainer { val data = context.newPersistentDataContainer() data.set(NamespacedKeys.BLOCK_KEY, PersistentDataType.LONG, complex.position) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt index 4208faed11..3e78ddc0b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt @@ -1,33 +1,45 @@ package net.horizonsend.ion.server.features.transport.filters +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType -data class FilterEntry(var value: T?, val type: FilterType, /*TODO configuration*/) { - companion object : PersistentDataType> { - override fun getComplexType(): Class> = FilterEntry::class.java +data class FilterEntry(var value: T?, val type: FilterType, val metaData: M) { + + companion object : PersistentDataType> { + override fun getComplexType(): Class> = FilterEntry::class.java override fun getPrimitiveType(): Class = PersistentDataContainer::class.java - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterEntry<*> { + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterEntry<*, *> { val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! val filterType = FilterType[filterTypeIdentifier] - return FilterEntry(filterType.retrieve(primitive), filterType) + val meta = primitive.get(NamespacedKeys.FILTER_META, PersistentDataType.TAG_CONTAINER) + + return FilterEntry( + filterType.retrieveValue(primitive), + filterType, + meta?.let { filterType.retrieveMeta(meta, context) } ?: filterType.buildEmptyMeta() + ) } - override fun toPrimitive(complex: FilterEntry<*>, context: PersistentDataAdapterContext): PersistentDataContainer { + override fun toPrimitive(complex: FilterEntry<*, *>, context: PersistentDataAdapterContext): PersistentDataContainer { val pdc = context.newPersistentDataContainer() val typeIdentifier = complex.type.identifier + // Store filter type for meta and data retrieval pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) + + // Store value if present complex.value?.let { complex.type.store(pdc, it) } + // Store meta data + pdc.set(NamespacedKeys.FILTER_META, MetaDataContainer, PDCSerializers.pack(complex.metaData)) + return pdc } - - @Suppress("UNCHECKED_CAST") - inline fun empty() = FilterEntry(null, FilterType[T::class] as FilterType) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt new file mode 100644 index 0000000000..38704d0661 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt @@ -0,0 +1,30 @@ +package net.horizonsend.ion.server.features.transport.filters + +import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers +import org.bukkit.persistence.PersistentDataAdapterContext +import org.bukkit.persistence.PersistentDataContainer + +interface FilterMeta { + data class ItemFilterMeta(var filterMethod: FilterMethod = FilterMethod.LENIENT) : FilterMeta { + companion object : PDCSerializers.RegisteredSerializer("ITEM_FILTER_META", ItemFilterMeta::class) { + val enumType = EnumDataType(FilterMethod::class.java) + + override fun toPrimitive(complex: ItemFilterMeta, context: PersistentDataAdapterContext, ): PersistentDataContainer { + val pdc = context.newPersistentDataContainer() + pdc.set(NamespacedKeys.SORTING_METHOD, enumType, complex.filterMethod) + return pdc + } + + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext, ): ItemFilterMeta { + return ItemFilterMeta(primitive.getOrDefault(NamespacedKeys.SORTING_METHOD, enumType, FilterMethod.LENIENT)) + } + } + } + + data object EmptyFilterMeta : PDCSerializers.RegisteredSerializer("EMPTY_META", EmptyFilterMeta::class), FilterMeta { + override fun toPrimitive(complex: EmptyFilterMeta, context: PersistentDataAdapterContext, ): PersistentDataContainer = context.newPersistentDataContainer() + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext, ): EmptyFilterMeta = EmptyFilterMeta + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt new file mode 100644 index 0000000000..e043378008 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt @@ -0,0 +1,38 @@ +package net.horizonsend.ion.server.features.transport.filters + +import io.papermc.paper.datacomponent.DataComponentTypes +import io.papermc.paper.datacomponent.item.ItemAttributeModifiers +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC +import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.updateData +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updateLore +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer +import net.kyori.adventure.text.Component.text +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataType + +enum class FilterMethod(val icon: ItemStack) { + STRICT(POWER_DRILL_BASIC.constructItemStack() + .updatePersistentDataContainer { + set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, "USELESS") + } + .updateData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP, true) + .updateData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().build()) + .apply { + POWER_DRILL_BASIC.getComponent(CustomComponentTypes.POWER_STORAGE).setPower(POWER_DRILL_BASIC, this, 25000) + } + .updateDisplayName(text("Strict item checks")) + .updateLore(mutableListOf(text("All item data will be matched."))) + ), + LENIENT(POWER_DRILL_BASIC.constructItemStack() + .updatePersistentDataContainer { + set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, "USELESS") + } + .updateData(DataComponentTypes.HIDE_ADDITIONAL_TOOLTIP, true) + .updateData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().build()) + .updateDisplayName(text("Lenient item checks")) + .updateLore(mutableListOf(text("Only item IDs will be matched."))) + ); +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index c043cf84c0..75669306fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -1,10 +1,13 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.common.utils.text.toComponent +import net.horizonsend.ion.server.features.transport.filters.FilterMeta.EmptyFilterMeta +import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updateLore import org.bukkit.Material @@ -14,7 +17,13 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType import kotlin.reflect.KClass -abstract class FilterType(val cacheType: CacheType, val identifier: String, val typeClass: Class, val persistentDataType: PersistentDataType<*, T>) { +abstract class FilterType( + val cacheType: CacheType, + val identifier: String, val + typeClass: Class, + val persistentDataType: PersistentDataType<*, T>, + val metaType: PDCSerializers.RegisteredSerializer +) { fun store(pdc: PersistentDataContainer, data: Any) { if (!typeClass.isInstance(data)) return if (data is ItemStack && data.isEmpty) { @@ -25,27 +34,37 @@ abstract class FilterType(val cacheType: CacheType, val identifier: Str pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, data as T) } - fun retrieve(pdc: PersistentDataContainer): T? { + fun retrieveValue(pdc: PersistentDataContainer): T? { return pdc.get(NamespacedKeys.FILTER_ENTRY, persistentDataType) } + fun retrieveMeta(pdc: PersistentDataContainer, context: PersistentDataAdapterContext): M { + return metaType.loadMetaDataContainer(pdc, context).data + } + + abstract fun buildEmptyMeta(): M + + fun buildEmptyEntry(): FilterEntry { + return FilterEntry(null, this, buildEmptyMeta()) + } + fun loadFilterEntries( primitive: List, context: PersistentDataAdapterContext - ): MutableList> { + ): MutableList> { return primitive.mapTo(mutableListOf()) { entry -> @Suppress("UNCHECKED_CAST") - FilterEntry.fromPrimitive(entry, context) as FilterEntry + FilterEntry.fromPrimitive(entry, context) as FilterEntry } } @Suppress("UNCHECKED_CAST") - fun cast(entry: FilterEntry<*>): FilterEntry = entry as FilterEntry + fun cast(entry: FilterEntry<*, *>): FilterEntry = entry as FilterEntry - abstract fun toItem(entry: FilterEntry): ItemStack? + abstract fun toItem(entry: FilterEntry): ItemStack? - data object FluidType : FilterType(CacheType.FLUID, "FLUID", Fluid::class.java, FluidPersistentDataType) { - override fun toItem(entry: FilterEntry): ItemStack? { + data object FluidType : FilterType(CacheType.FLUID, "FLUID", Fluid::class.java, FluidPersistentDataType, PDCSerializers.EMPTY_FILTER_META) { + override fun toItem(entry: FilterEntry): ItemStack? { val value = entry.value if (value == null) return null @@ -53,19 +72,23 @@ abstract class FilterType(val cacheType: CacheType, val identifier: Str .updateDisplayName(value.displayName) .updateLore(value.categories.map { it.toComponent() }) } + + override fun buildEmptyMeta(): EmptyFilterMeta = EmptyFilterMeta } - data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemSerializer) { - override fun toItem(entry: FilterEntry): ItemStack? = entry.value?.clone() + data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemSerializer, PDCSerializers.ITEM_FILTER_META) { + override fun toItem(entry: FilterEntry): ItemStack? = entry.value?.clone() + + override fun buildEmptyMeta(): ItemFilterMeta = ItemFilterMeta() } companion object { private val byId = mapOf("FLUID" to FluidType, "ITEMS" to ItemType) - operator fun get(identifier: String): FilterType<*> = byId[identifier] ?: throw NoSuchElementException("Filter type $identifier not found") + operator fun get(identifier: String): FilterType<*, *> = byId[identifier] ?: throw NoSuchElementException("Filter type $identifier not found") - private val byClass: Map, FilterType<*>> = mapOf(Fluid::class to FluidType, ItemStack::class to ItemType) + private val byClass: Map, FilterType<*, *>> = mapOf(Fluid::class to FluidType, ItemStack::class to ItemType) - operator fun get(clazz: KClass<*>): FilterType<*> = byClass[clazz] ?: throw NoSuchElementException("Filter type for ${clazz.simpleName} not found") + operator fun get(clazz: KClass<*>): FilterType<*, *> = byClass[clazz] ?: throw NoSuchElementException("Filter type for ${clazz.simpleName} not found") } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt index 08e3f77429..8763eb5b40 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.filters.manager import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import net.horizonsend.ion.server.features.custom.blocks.filter.CustomFilterBlock import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -12,25 +13,25 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.block.CommandBlock abstract class FilterManager(val manager: TransportManager<*>) { - val filters = Long2ObjectOpenHashMap>() + val filters = Long2ObjectOpenHashMap>() private val mutex = Any() - fun getFilters(): Collection> { + fun getFilters(): Collection> { return filters.values } - fun getFilters(type: FilterType): Collection> { + fun getFilters(type: FilterType): Collection> { return filters.values .filter { data -> data.type == type } - .filterIsInstance>() + .filterIsInstance>() } - fun getFilter(key: BlockKey): FilterData<*>? { + fun getFilter(key: BlockKey): FilterData<*, *>? { return filters[key] } - fun addFilter(key: BlockKey, data: FilterData<*>) { + fun addFilter(key: BlockKey, data: FilterData<*, *>) { val local = manager.getLocalCoordinate(toVec3i(key)) synchronized(mutex) { @@ -38,14 +39,14 @@ abstract class FilterManager(val manager: TransportManager<*>) { } } - fun > registerFilter(key: BlockKey, block: CustomFilterBlock): D { + fun registerFilter(key: BlockKey, block: CustomFilterBlock): FilterData { val global = manager.getGlobalCoordinate(toVec3i(key)) val world = manager.getWorld() val state = world.getBlockState(global.x, global.y, global.z) as? CommandBlock @Suppress("UNCHECKED_CAST") - val data = state?.persistentDataContainer?.get(NamespacedKeys.FILTER_DATA, FilterData) as? D ?: block.createData(key) + val data = state?.persistentDataContainer?.get(NamespacedKeys.FILTER_DATA, FilterData) as? FilterData ?: block.createData(key) addFilter(key, data) @@ -64,7 +65,7 @@ abstract class FilterManager(val manager: TransportManager<*>) { abstract fun load() companion object { - fun save(commandBlock: CommandBlock, data: FilterData<*>) { + fun save(commandBlock: CommandBlock, data: FilterData<*, *>) { commandBlock.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, data) commandBlock.update() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 6341fb60ab..be82985e65 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -92,6 +92,8 @@ object NamespacedKeys { val FILTER_DATA = key("filter_data") val FILTER_TYPE = key("filter_type") val FILTER_ENTRY = key("filter_entry") + val SORTING_METHOD = key("sorting_method") + val FILTER_META = key("filter_meta") val WHITELIST = key("whitelist") val POWER_TRANSPORT = key("power_transport") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt index 4e1e2907b6..4fd3d2e887 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.miscellaneous.registrations.persistence import net.horizonsend.ion.server.features.transport.filters.FilterData.FilterDataSerializer +import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer @@ -19,6 +20,8 @@ object PDCSerializers { val ITEM_EXTRACTOR_METADATA = register(ItemExtractorData.ItemExtractorMetaData.Companion) val FILTER_DATA = register(FilterDataSerializer) + val EMPTY_FILTER_META = register(FilterMeta.EmptyFilterMeta) + val ITEM_FILTER_META = register(FilterMeta.ItemFilterMeta) operator fun get(identifier: String) : RegisteredSerializer<*> = registeredSerializers[identifier]!! From d116f8ca697b96cea09395d0c7ac6436d6dfa6b9 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 26 Jan 2025 15:32:23 -0600 Subject: [PATCH 432/500] integrate filter into nodes --- .../features/transport/filters/FilterData.kt | 12 +++ .../features/transport/filters/FilterEntry.kt | 10 ++- .../transport/filters/FilterMethod.kt | 20 ++++- .../features/transport/filters/FilterType.kt | 35 +++++++- .../filters/manager/FilterManager.kt | 4 + .../transport/nodes/types/ItemNode.kt | 82 ++++++++++++++++++- .../features/transport/old/pipe/Pipes.kt | 25 +++--- .../transport/old/pipe/filter/Filters.kt | 6 +- .../{FilterData.kt => LegacyFilterData.kt} | 2 +- 9 files changed, 170 insertions(+), 26 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/{FilterData.kt => LegacyFilterData.kt} (68%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt index 8d13465e74..99bd418199 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterData.kt @@ -13,6 +13,18 @@ data class FilterData( var entries: MutableList> = mutableListOf(), var isWhitelist: Boolean = true, ) { + fun matchesFilter(data: T): Boolean { + val nonEmpty = entries.filterNot(FilterEntry<*, *>::isEmpty) + + return if (isWhitelist) nonEmpty.any { entry -> + // In a whitelist, any entry being true would let it through + entry.matches(data = data, isWhitelist = true) + } else nonEmpty.all { entry -> + // In a blacklist, all entries must return true (not filter it out) to let it through + entry.matches(data = data, isWhitelist = false) + } + } + companion object FilterDataSerializer : PDCSerializers.RegisteredSerializer>("FILTER_DATA", FilterData::class) { override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): FilterData<*, *> { val whitelist = primitive.getOrDefault(NamespacedKeys.WHITELIST, PersistentDataType.BOOLEAN, true) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt index 3e78ddc0b2..fa54f3ac41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt @@ -8,6 +8,14 @@ import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType data class FilterEntry(var value: T?, val type: FilterType, val metaData: M) { + fun matches(data: Any, isWhitelist: Boolean): Boolean { + if (!type.typeClass.isInstance(data)) return false + if (value == null) return !isWhitelist + + return type.castAndMatch(data, isWhitelist = isWhitelist, entry = this) + } + + fun isEmpty() = value == null companion object : PersistentDataType> { override fun getComplexType(): Class> = FilterEntry::class.java @@ -34,7 +42,7 @@ data class FilterEntry(var value: T?, val type: FilterT pdc.set(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING, typeIdentifier) // Store value if present - complex.value?.let { complex.type.store(pdc, it) } + complex.type.store(pdc, complex.value) // Store meta data pdc.set(NamespacedKeys.FILTER_META, MetaDataContainer, PDCSerializers.pack(complex.metaData)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt index e043378008..6519e4785d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMethod.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.filters import io.papermc.paper.datacomponent.DataComponentTypes import io.papermc.paper.datacomponent.item.ItemAttributeModifiers import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.updateData @@ -25,7 +26,11 @@ enum class FilterMethod(val icon: ItemStack) { } .updateDisplayName(text("Strict item checks")) .updateLore(mutableListOf(text("All item data will be matched."))) - ), + ) { + override fun matches(data: ItemStack, target: ItemStack): Boolean { + return data.isSimilar(target) + } + }, LENIENT(POWER_DRILL_BASIC.constructItemStack() .updatePersistentDataContainer { set(NamespacedKeys.CUSTOM_ITEM, PersistentDataType.STRING, "USELESS") @@ -34,5 +39,16 @@ enum class FilterMethod(val icon: ItemStack) { .updateData(DataComponentTypes.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.itemAttributes().build()) .updateDisplayName(text("Lenient item checks")) .updateLore(mutableListOf(text("Only item IDs will be matched."))) - ); + ) { + override fun matches(data: ItemStack, target: ItemStack): Boolean { + val customItem = target.customItem + if (customItem != null) { + return data.customItem == customItem + } + + return target.type == data.type + } + }; + + abstract fun matches(data: ItemStack, target: ItemStack): Boolean } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index 75669306fa..9be2c840e2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -19,19 +19,22 @@ import kotlin.reflect.KClass abstract class FilterType( val cacheType: CacheType, - val identifier: String, val - typeClass: Class, + val identifier: String, + val typeClass: Class, val persistentDataType: PersistentDataType<*, T>, val metaType: PDCSerializers.RegisteredSerializer ) { - fun store(pdc: PersistentDataContainer, data: Any) { + fun castAndMatch(data: Any, isWhitelist: Boolean, entry: FilterEntry): Boolean = matches(cast(data), isWhitelist, entry) + abstract fun matches(data: T, isWhitelist: Boolean, entry: FilterEntry): Boolean + + fun store(pdc: PersistentDataContainer, data: Any?) { if (!typeClass.isInstance(data)) return if (data is ItemStack && data.isEmpty) { return } @Suppress("UNCHECKED_CAST") - pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, data as T) + data?.let { pdc.set(NamespacedKeys.FILTER_ENTRY, persistentDataType, it as T) } } fun retrieveValue(pdc: PersistentDataContainer): T? { @@ -61,6 +64,11 @@ abstract class FilterType( @Suppress("UNCHECKED_CAST") fun cast(entry: FilterEntry<*, *>): FilterEntry = entry as FilterEntry + @Suppress("UNCHECKED_CAST") + fun cast(data: FilterData<*, *>): FilterData = data as FilterData + + fun cast(data: Any): T = data as T + abstract fun toItem(entry: FilterEntry): ItemStack? data object FluidType : FilterType(CacheType.FLUID, "FLUID", Fluid::class.java, FluidPersistentDataType, PDCSerializers.EMPTY_FILTER_META) { @@ -74,12 +82,31 @@ abstract class FilterType( } override fun buildEmptyMeta(): EmptyFilterMeta = EmptyFilterMeta + + override fun matches( + data: Fluid, + isWhitelist: Boolean, + entry: FilterEntry, + ): Boolean { + val matched = entry.value ?: return true + return matched == data + } } data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemSerializer, PDCSerializers.ITEM_FILTER_META) { override fun toItem(entry: FilterEntry): ItemStack? = entry.value?.clone() override fun buildEmptyMeta(): ItemFilterMeta = ItemFilterMeta() + + override fun matches( + data: ItemStack, + isWhitelist: Boolean, + entry: FilterEntry, + ): Boolean { + if (entry.value !is ItemStack) return true + + return (entry.metaData as ItemFilterMeta).filterMethod.matches(data, entry.value as ItemStack) == isWhitelist + } } companion object { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt index 8763eb5b40..28c03a4f2c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -31,6 +31,10 @@ abstract class FilterManager(val manager: TransportManager<*>) { return filters[key] } + fun getFilter(key: BlockKey, type: FilterType): FilterData? { + return filters[key]?.let { data -> type.cast(data) } + } + fun addFilter(key: BlockKey, data: FilterData<*, *>) { val local = manager.getLocalCoordinate(toVec3i(key)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 767bacb04e..31f6e1d6c3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -1,15 +1,27 @@ package net.horizonsend.ion.server.features.transport.nodes.types +import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem +import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.filters.FilterData +import net.horizonsend.ion.server.features.transport.filters.FilterMeta +import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.PipeChannel.entries +import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextColor.fromHexString import org.bukkit.Material import org.bukkit.block.BlockFace +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack +import java.lang.ref.WeakReference interface ItemNode : Node { override val cacheType: CacheType get() = CacheType.ITEMS @@ -29,7 +41,9 @@ interface ItemNode : Node { override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - sealed interface ChanneledItemNode { + sealed interface IntermediateNode + + sealed interface ChanneledItemNode : IntermediateNode { val channel: PipeChannel /** @@ -81,6 +95,72 @@ interface ItemNode : Node { override val pathfindingResistance: Double = 1.0 } + sealed interface FilterNode : ItemNode { + fun matches(itemStack: ItemStack) : Boolean + } + + data class AdvancedFilterNode(val position: BlockKey, val cache: ItemTransportCache) : FilterNode { + val filter: WeakReference> = WeakReference(cache.holder.transportManager.filterManager.getFilter(position, FilterType.ItemType)!!) + override val pathfindingResistance: Double = 1.0 + + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is InventoryNode + + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode + + override fun matches(itemStack: ItemStack): Boolean { + return filter.get()?.matchesFilter(itemStack) == true + } + } + + data class HopperFilterNode(val position: BlockKey, var face: BlockFace, val cache: ItemTransportCache) : FilterNode, ComplexNode { + val globalPosition get() = cache.holder.transportManager.getGlobalCoordinate(toVec3i(position)) + override val pathfindingResistance: Double = 1.0 + + override fun getTransferableDirections(backwards: BlockFace): Set = setOf(face) + + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is InventoryNode + + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode + + override fun matches(itemStack: ItemStack): Boolean { + val inventory = cache.getInventory(toBlockKey(globalPosition)) ?: return false + val filterData = getItemData(inventory) + + val itemData = createFilterItemData(itemStack) + return filterData.any { data -> data == itemData } + } + + override fun displace(movement: StarshipMovement) { + face = movement.displaceFace(face) + } + + data class LegacyFilterData(val items: Set, val face: BlockFace) { + override fun toString(): String = "[$items towards $face]" + } + + fun getItemData(inventory: Inventory): Set { + val types = mutableSetOf() + + for (item: ItemStack? in inventory.contents) { + val type = item?.type ?: continue + + if (type.isAir) { + continue + } + + types.add(createFilterItemData(item)) + } + + return types + } + + fun createFilterItemData(item: ItemStack): FilterItemData { + return FilterItemData(item.type, item.customItem?.identifier) + } + } + enum class PipeChannel(val solidMaterial: Material, val paneMaterial: Material, val textColor: TextColor) { WHITE(Material.WHITE_STAINED_GLASS, Material.WHITE_STAINED_GLASS_PANE, NamedTextColor.WHITE), LIGHT_GRAY(Material.LIGHT_GRAY_STAINED_GLASS, Material.LIGHT_GRAY_STAINED_GLASS_PANE, NamedTextColor.GRAY), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt index 23ff70c864..2068e8382e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/Pipes.kt @@ -6,9 +6,9 @@ import net.horizonsend.ion.server.features.custom.items.type.GasCanister import net.horizonsend.ion.server.features.gas.type.GasFuel import net.horizonsend.ion.server.features.gas.type.GasOxidizer import net.horizonsend.ion.server.features.machine.GeneratorFuel -import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterData import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.old.pipe.filter.Filters +import net.horizonsend.ion.server.features.transport.old.pipe.filter.LegacyFilterData import net.horizonsend.ion.server.features.transport.old.transportConfig import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.MATERIALS @@ -43,9 +43,6 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set object Pipes : IonServerComponent() { private lateinit var thread: ExecutorService @@ -205,7 +202,7 @@ object Pipes : IonServerComponent() { val sidePipes = mutableListOf() val sideInventories = mutableListOf() - val filters = mutableMapOf() + val filters = mutableMapOf() val filterItems = mutableMapOf>() val reverse = data.direction.oppositeFace @@ -295,7 +292,7 @@ object Pipes : IonServerComponent() { nx: Int, ny: Int, nz: Int, - filters: MutableMap, + filters: MutableMap, filterItems: MutableMap> ) { val sidePipeFace: BlockFace = pickDirection(nextType, sidePipes, data.direction) @@ -317,24 +314,24 @@ object Pipes : IonServerComponent() { private fun handleFilter( data: PipeChainData, - filterData: FilterData, + legacyFilterData: LegacyFilterData, sideX: Int, sideY: Int, sideZ: Int, sidePipes: MutableList, sideFace: BlockFace, - sideFilters: MutableMap, + sideFilters: MutableMap, sideFilterItems: MutableMap> ) { - val combinedFilter = data.accumulatedFilter.intersect(filterData.items) + val combinedFilter = data.accumulatedFilter.intersect(legacyFilterData.items) if (combinedFilter.isEmpty()) { return } - val pipeX = sideX + filterData.face.modX - val pipeY = sideY + filterData.face.modY - val pipeZ = sideZ + filterData.face.modZ + val pipeX = sideX + legacyFilterData.face.modX + val pipeY = sideY + legacyFilterData.face.modY + val pipeZ = sideZ + legacyFilterData.face.modZ val pipeType = getBlockTypeSafe(data.world, pipeX, pipeY, pipeZ) ?: return @@ -343,7 +340,7 @@ object Pipes : IonServerComponent() { } sidePipes.add(sideFace) - sideFilters[sideFace] = filterData + sideFilters[sideFace] = legacyFilterData sideFilterItems[sideFace] = combinedFilter } /** Helper function for filtering direction for grindstones by matching proposal with @@ -393,7 +390,7 @@ object Pipes : IonServerComponent() { val z: Int, val inventories: List, val pipes: List, - val filters: MutableMap, + val filters: MutableMap, val filterItems: MutableMap> ) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt index de4344e959..ae2e55de37 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/Filters.kt @@ -24,7 +24,7 @@ import org.bukkit.inventory.ItemStack import java.util.concurrent.TimeUnit object Filters : IonServerComponent() { - private val cache: LoadingCache = CacheBuilder.newBuilder() + private val cache: LoadingCache = CacheBuilder.newBuilder() .expireAfterWrite(1L, TimeUnit.MINUTES) .build( CacheLoader.from { key -> @@ -38,7 +38,7 @@ object Filters : IonServerComponent() { val items: Set = getItemData(inventory) val face: BlockFace = (state.blockData as Directional).facing - return@from FilterData(items, face) + return@from LegacyFilterData(items, face) } ) @@ -65,7 +65,7 @@ object Filters : IonServerComponent() { private fun getKey(world: World, x: Int, y: Int, z: Int) = FilterDataKey(world.uid, Vec3i(x, y, z)) - fun getCached(world: World, x: Int, y: Int, z: Int): FilterData? { + fun getCached(world: World, x: Int, y: Int, z: Int): LegacyFilterData? { return cache.getIfPresent(getKey(world, x, y, z)) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/LegacyFilterData.kt similarity index 68% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterData.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/LegacyFilterData.kt index 0ffd750fd7..48ffe2f281 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/FilterData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/old/pipe/filter/LegacyFilterData.kt @@ -2,7 +2,7 @@ package net.horizonsend.ion.server.features.transport.old.pipe.filter import org.bukkit.block.BlockFace -data class FilterData(val items: Set, val face: BlockFace) { +data class LegacyFilterData(val items: Set, val face: BlockFace) { override fun toString(): String { return "[$items towards $face]" } From a9cf14e00fc5e313a7ee875ca1ce2245764e1971 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 26 Jan 2025 21:47:47 -0600 Subject: [PATCH 433/500] Use filters when pathfinding --- .../nodes/cache/ItemTransportCache.kt | 78 ++++++++++++++++--- .../transport/nodes/cache/NodeCacheFactory.kt | 12 ++- .../transport/nodes/types/ItemNode.kt | 20 ++--- 3 files changed, 85 insertions(+), 25 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index a06932d680..cecc2358dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.common.extensions.information +import net.horizonsend.ion.common.extensions.serverError import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock @@ -12,6 +13,7 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.data.Ite import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode +import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES @@ -25,9 +27,13 @@ import net.minecraft.core.BlockPos import net.minecraft.world.Container import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.block.BlockFace +import org.bukkit.block.data.type.CommandBlock +import org.bukkit.block.data.type.Hopper import org.bukkit.craftbukkit.block.impl.CraftGrindstone import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack class ItemTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.ITEMS @@ -40,6 +46,8 @@ class ItemTransportCache(holder: CacheHolder): TransportCach .addSimpleNode(Material.GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(Material.TINTED_GLASS, ItemNode.WildcardSolidGlassNode) .addDataHandler(Material.GRINDSTONE) { data, key -> ItemNode.ItemMergeNode } + .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key -> ItemNode.AdvancedFilterNode(key, this) } + .addDataHandler(Material.HOPPER) { data, key -> ItemNode.HopperFilterNode(key, data.facing, this) } .addSimpleNode( Material.CHEST, Material.TRAPPED_CHEST, @@ -56,8 +64,6 @@ class ItemTransportCache(holder: CacheHolder): TransportCach delta: Double, metaData: ExtractorMetaData?, ) { -// return - NewTransport.executor.submit { measureOrFallback(TransportDebugCommand.extractorTickTimes) { handleExtractorTick(location, delta, metaData as? ItemExtractorMetaData) @@ -73,18 +79,68 @@ class ItemTransportCache(holder: CacheHolder): TransportCach return } - val destinations: List = getNetworkDestinations(location) { node -> - val inventory = getInventory(node.position) - inventory != null && inventory.isEmpty //TODO full - }.toList() + val items = sources.flatMap { inv -> inv }.filterNotNull() + if (items.isEmpty()) return + + val byCount = mutableMapOf() - val destination = if (meta != null) distributionOrder.getDestination(meta, destinations) else { - val extractorPosition = toVec3i(location) - destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } + for (item in items) { + val asOne = item.asOne() + if (byCount.containsKey(asOne)) continue + val count = items.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } + byCount[asOne] = count } - debugAudience.highlightBlock(toVec3i(destination), 40L) - debugAudience.information("Destinations: ${destinations.size}") + debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") + + for ((item, count) in byCount) { + debugAudience.information("Checking ${item.type} [$count]") + val destinations: List = getNetworkDestinations(location) { node -> + val inventory = getInventory(node.position) + inventory != null && inventory.isEmpty //TODO full + }.toList() + + if (destinations.isEmpty()) { + debugAudience.information("No destinations found") + continue + } + + val numDestinations = destinations.size + + val paths: Array = measureOrFallback(TransportDebugCommand.pathfindTimes) { Array(numDestinations) { + getOrCachePath( + Node.NodePositionData( + ItemNode.ItemExtractorNode, + holder.getWorld(), + location, + BlockFace.SELF + ), + destinations[it] + ) { node, blockFace -> + if (node !is ItemNode.FilterNode) return@getOrCachePath true + debugAudience.serverError("checking filter") + node.matches(item) + } + } } + + val validDestinations = destinations.filterIndexed { index, _ -> + paths[index] != null + } + + if (validDestinations.isEmpty()) { + debugAudience.serverError("Could not find valid destination.") + println(paths.toList()) + } + + val destination = if (meta != null) { + distributionOrder.getDestination(meta, validDestinations) + } else { + val extractorPosition = toVec3i(location) + destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } + } + + debugAudience.highlightBlock(toVec3i(destination), 40L) + } } fun getInventory(key: BlockKey): Inventory? { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 177788587c..4974d33c10 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -10,7 +10,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.data.BlockData -import org.bukkit.block.data.MultipleFacing import kotlin.reflect.KClass class NodeCacheFactory private constructor(private val materialHandlers: Map>) { @@ -32,6 +31,15 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map addDataHandler(customBlock: CustomBlock, noinline constructor: (T, BlockKey) -> Node?): Builder { + require(customBlock.blockData is T) + + return addDataHandler(customBlock.blockData.material) { data, lng -> + if (CustomBlocks.getByBlockData(data) != customBlock) return@addDataHandler null + constructor.invoke(data, lng) + } + } + inline fun addDataHandler(materials: Iterable, noinline constructor: (T, BlockKey) -> Node): Builder { for (material in materials) this.materialHandlers[material] = MaterialHandler(T::class, constructor) return this @@ -63,7 +71,7 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map(Material.BROWN_MUSHROOM_BLOCK) { data, lng -> + return addDataHandler(customBlock.blockData.material) { data, lng -> if (CustomBlocks.getByBlockData(data) != customBlock) return@addDataHandler null node } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 31f6e1d6c3..80c198a9e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -79,14 +79,6 @@ interface ItemNode : Node { override val pathfindingResistance: Double = 1.0 } - data object WildcardPaneGlassNode : ItemNode { - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - - override val pathfindingResistance: Double = 1.0 - } - data object ItemMergeNode : ItemNode { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO @@ -112,6 +104,10 @@ interface ItemNode : Node { override fun matches(itemStack: ItemStack): Boolean { return filter.get()?.matchesFilter(itemStack) == true } + + override fun toString(): String { + return filter.get().toString() + } } data class HopperFilterNode(val position: BlockKey, var face: BlockFace, val cache: ItemTransportCache) : FilterNode, ComplexNode { @@ -136,10 +132,6 @@ interface ItemNode : Node { face = movement.displaceFace(face) } - data class LegacyFilterData(val items: Set, val face: BlockFace) { - override fun toString(): String = "[$items towards $face]" - } - fun getItemData(inventory: Inventory): Set { val types = mutableSetOf() @@ -159,6 +151,10 @@ interface ItemNode : Node { fun createFilterItemData(item: ItemStack): FilterItemData { return FilterItemData(item.type, item.customItem?.identifier) } + + override fun toString(): String { + return getItemData(cache.getInventory(toBlockKey(globalPosition))!!).toString() + } } enum class PipeChannel(val solidMaterial: Material, val paneMaterial: Material, val textColor: TextColor) { From 81b13995be216c543a356e5a3435408ee9861ac6 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Mon, 27 Jan 2025 01:21:26 -0600 Subject: [PATCH 434/500] Path cache invalidation --- .../command/misc/TransportDebugCommand.kt | 5 +- .../nodes/cache/FluidTransportCache.kt | 6 +- .../nodes/cache/ItemTransportCache.kt | 6 +- .../nodes/cache/PowerTransportCache.kt | 11 ++- .../transport/nodes/cache/SolarPanelCache.kt | 4 + .../transport/nodes/cache/TransportCache.kt | 96 +++++++++++++++---- .../features/transport/nodes/types/Node.kt | 32 +++++++ 7 files changed, 134 insertions(+), 26 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index f654066dad..9ea80bfbf7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -204,9 +204,10 @@ object TransportDebugCommand : SLCommand() { @Subcommand("test flood") fun onTestFloodFill(sender: Player, type: CacheType) { sender.information("Trying to find input nodes") - val (_, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } + val (node, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } val cache = type.get(sender.chunk.ion()) - val destinations = cache.getNetworkDestinations(location) { true } + + val destinations = cache.getNetworkDestinations(location, node) { true } sender.information("${destinations.size} destinations") sender.highlightBlocks(destinations.map(::toVec3i), 50L) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index ffc73b846d..925bcb0aa1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -25,9 +25,11 @@ import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.block.impl.CraftLightningRod import kotlin.math.roundToInt +import kotlin.reflect.KClass class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.FLUID + override val extractorNodeClass: KClass = FluidNode.FluidExtractorNode::class override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addDataHandler(Material.LIGHTNING_ROD) { data, _ -> FluidNode.LightningRodNode(data.facing.axis) } .addSimpleNode(WAXED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_CHISELED_COPPER) } @@ -49,8 +51,10 @@ class FluidTransportCache(holder: CacheHolder): TransportCa if (source.getStoredResources().isEmpty()) return@submit + val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), location) ?: return@submit + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power - val destinations: Collection = getNetworkDestinations(location) { node -> + val destinations: Collection = getNetworkDestinations(location, originNode) { node -> world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index cecc2358dc..8a8c3c1c3e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -34,9 +34,11 @@ import org.bukkit.craftbukkit.block.impl.CraftGrindstone import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack +import kotlin.reflect.KClass class ItemTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.ITEMS + override val extractorNodeClass: KClass = ItemNode.ItemExtractorNode::class override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) .addSimpleNode(CustomBlocks.ADVANCED_ITEM_EXTRACTOR, ItemNode.ItemExtractorNode) @@ -93,9 +95,11 @@ class ItemTransportCache(holder: CacheHolder): TransportCach debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") + val originNode = getOrCache(location) ?: return + for ((item, count) in byCount) { debugAudience.information("Checking ${item.type} [$count]") - val destinations: List = getNetworkDestinations(location) { node -> + val destinations: List = getNetworkDestinations(location, originNode) { node -> val inventory = getInventory(node.position) inventory != null && inventory.isEmpty //TODO full }.toList() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 0d43d7ccfa..b9bc10a50c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -26,9 +26,12 @@ import org.bukkit.block.BlockFace import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.block.impl.CraftEndRod import kotlin.math.roundToInt +import kotlin.reflect.KClass class PowerTransportCache(holder: CacheHolder) : TransportCache(holder) { override val type: CacheType = CacheType.POWER + override val extractorNodeClass: KClass = PowerNode.PowerExtractorNode::class + override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) .addSimpleNode(SPONGE, PowerNode.SpongeNode) @@ -54,9 +57,11 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val sources = getExtractorSourceEntities(location) { it.powerStorage.isEmpty() } val source = sources.randomOrNull() ?: return@measureOrFallback //TODO take from all + val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), location) ?: return@measureOrFallback + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power val destinations: Collection = measureOrFallback(TransportDebugCommand.floodFillTimes) { - getNetworkDestinations(location) { node -> + getNetworkDestinations(location, originNode) { node -> getInputEntities(node.position).any { entity -> (entity is PoweredMultiblockEntity) && !entity.powerStorage.isFull() } @@ -95,9 +100,11 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val transportPower = solarCache.getPower(holder.getWorld(), location, delta) if (transportPower == 0) return@measureOrFallback + val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), location) ?: return@measureOrFallback + // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power val destinations: Collection = measureOrFallback(TransportDebugCommand.solarFloodFillTimes) { - getNetworkDestinations(location) { node -> + getNetworkDestinations(location, originNode) { node -> getInputEntities(node.position).any { entity -> (entity is PoweredMultiblockEntity) && !entity.powerStorage.isFull() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt index 8692805185..066f29cee8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative @@ -14,6 +15,7 @@ import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.data.type.DaylightDetector import kotlin.math.roundToInt +import kotlin.reflect.KClass class SolarPanelCache(holder: CacheHolder) : TransportCache(holder) { override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() @@ -24,6 +26,8 @@ class SolarPanelCache(holder: CacheHolder) : TransportCache(hol override val type: CacheType = CacheType.SOLAR_PANELS + override val extractorNodeClass: KClass = PowerNode.PowerExtractorNode::class + sealed interface SolarPanelComponent: Node { data object CraftingTable: SolarPanelComponent data object DiamondBlock: SolarPanelComponent diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 35b22eec06..c34c133311 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import com.google.common.collect.TreeBasedTable import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData @@ -22,6 +23,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isAdjacent import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.set import org.bukkit.block.Block @@ -29,19 +31,29 @@ import org.bukkit.block.BlockFace import java.util.Optional import java.util.concurrent.ConcurrentHashMap import kotlin.jvm.optionals.getOrNull +import kotlin.reflect.KClass abstract class TransportCache(val holder: CacheHolder<*>) { - private var cache: ConcurrentHashMap = ConcurrentHashMap() + /** + * Cache containing a cache state at their corresponding block position. + * The state can either be empty, or present. Empty key / value pairs have not been cached. + **/ + private var nodeCache: ConcurrentHashMap = ConcurrentHashMap() + + /** + * A table containing cached paths. The first value is the origin of the path, usually an extractor, and the second is the destination location. + **/ + private val pathCache = TreeBasedTable.create>() abstract val type: CacheType abstract val nodeFactory: NodeCacheFactory abstract fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) - fun isCached(at: BlockKey): Boolean = cache.containsKey(at) + fun isCached(at: BlockKey): Boolean = nodeCache.containsKey(at) fun getCached(at: BlockKey): Node? { - val state = cache[at] ?: return null + val state = nodeCache[at] ?: return null return when (state) { is CacheState.Empty -> null is CacheState.Present -> state.node @@ -63,12 +75,12 @@ abstract class TransportCache(val holder: CacheHolder<*>) { fun cache(location: BlockKey, block: Block): Node? = synchronized(mutex) { // On race conditions - cache[location]?.let { return@synchronized (it as? CacheState.Present)?.node } + nodeCache[location]?.let { return@synchronized (it as? CacheState.Present)?.node } val type = nodeFactory.cache(block) val state = if (type == null) CacheState.Empty else CacheState.Present(type) - cache[location] = state + nodeCache[location] = state return type } @@ -76,11 +88,15 @@ abstract class TransportCache(val holder: CacheHolder<*>) { invalidate(toBlockKey(x, y, z)) } + abstract val extractorNodeClass: KClass + fun invalidate(key: BlockKey) { - (cache.remove(key) as? CacheState.Present)?.node?.onInvalidate() + val removed = (nodeCache.remove(key) as? CacheState.Present)?.node + removed?.onInvalidate() ?: return + invalidatePaths(key, removed) } - fun getRawCache() = cache + fun getRawCache() = nodeCache fun displace(movement: StarshipMovement) { for (state in getRawCache().values) { @@ -161,10 +177,17 @@ abstract class TransportCache(val holder: CacheHolder<*>) { inline fun getNetworkDestinations( originPos: BlockKey, - check: (Node.NodePositionData) -> Boolean, - ): Collection { - val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), originPos) ?: return listOf() + originNode: Node, + noinline check: ((Node.NodePositionData) -> Boolean)? = null + ): Collection = getNetworkDestinations(T::class, originPos, originNode, check) + fun getNetworkDestinations( + clazz: KClass, + originPos: BlockKey, + originNode: Node, + nodeCheck: ((Node.NodePositionData) -> Boolean)? = null, + nextNodeProvider: Node.NodePositionData.() -> List = { getNextNodes(holder.nodeProvider, null) } + ): Collection { val visitQueue = ArrayDeque() val visited = LongOpenHashSet() val destinations = LongOpenHashSet() @@ -181,30 +204,63 @@ abstract class TransportCache(val holder: CacheHolder<*>) { val current = visitQueue.removeFirst() visited.add(current.position) - if (current.type is T && check(current)) { + if (clazz.isInstance(current.type) && (nodeCheck?.invoke(current) != false)) { destinations.add(current.position) } - visitQueue.addAll(current.getNextNodes(holder.nodeProvider, null).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) + visitQueue.addAll(nextNodeProvider(current).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) } return destinations } - /** - * - **/ - private val simplePathCache = TreeBasedTable.create>() + private val pathCacheLock = Any() + + fun invalidatePaths(pos: BlockKey, node: Node) { + val toRemove = mutableSetOf>() + + // If the pos is an origin or destination, there is no need to perform a flood to find the connected rows / destinations + // If the path cache contains a row at this pos, an origin is present here, and it can be removed + if (pathCache.containsRow(pos)) { + pathCache.rowMap()[pos]?.keys?.forEach { columnKey -> + toRemove.add(pos to columnKey) + } + } + + // If the path cache contains a column at this pos, a destination from an origin within the chunk can be invalidated + if (pathCache.containsColumn(pos)) { + pathCache.columnMap()[pos]?.keys?.forEach { rowKey -> + toRemove.add(rowKey to pos) + } + } + + // Perform a flood fill to find all network destinations, then remove all destination columns + getNetworkDestinations(clazz = extractorNodeClass, originPos = pos, originNode = node) { + // Traverse network backwards + getPreviousNodes(holder.nodeProvider, null) + }.forEach { extractorPos -> + debugAudience.highlightBlock(holder.transportManager.getGlobalCoordinate(toVec3i(extractorPos)), 10L) + + pathCache.rowMap()[extractorPos]?.keys?.forEach { columnKey -> + toRemove.add(extractorPos to columnKey) + } + } + + // Remove all the paths after being found + synchronized(pathCacheLock) { + for ((rowKey, columnKey) in toRemove) pathCache.remove(rowKey, columnKey) + } + } fun getOrCachePath(origin: Node.NodePositionData, destination: BlockKey, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): PathfindingReport? { - if (simplePathCache.contains(origin.position, destination)) { - return simplePathCache.get(origin.position, destination)?.getOrNull() + if (pathCache.contains(origin.position, destination)) { + return synchronized(pathCacheLock) { pathCache.get(origin.position, destination)?.getOrNull() } } val path = runCatching { getIdealPath(origin, destination, holder.nodeProvider, pathfindingFilter) }.getOrNull() if (path == null) { - simplePathCache[origin.position, destination] = Optional.empty() + synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.empty() } return null } @@ -212,7 +268,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { val report = PathfindingReport(path, resistance) - simplePathCache[origin.position, destination] = Optional.of(report) + synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.of(report) } return report } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt index eb4f098d40..1e6be8dc58 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/Node.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.nodes.types import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import org.bukkit.World @@ -46,6 +47,34 @@ interface Node { return filterPositionData(nodes, backwards) } + /** Altered node provider, designed for traversing networks backwards */ + fun getPreviousNodes( + world: World, + position: BlockKey, + backwards: BlockFace, + cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, + filter: ((Node, BlockFace) -> Boolean)? + ): List { + val nodes = mutableListOf() + + for (adjacentFace in ADJACENT_BLOCK_FACES) { + val relativePos = getRelative(position, adjacentFace) + val cached = cachedNodeProvider.invoke(cacheType, world, relativePos) ?: continue + + if (!cached.canTransferTo(this, adjacentFace.oppositeFace) || !canTransferFrom(cached, adjacentFace.oppositeFace)) continue + if (filter != null && !filter.invoke(cached, adjacentFace.oppositeFace)) continue + + nodes.add(NodePositionData( + type = cached, + world = world, + position = getRelative(position, adjacentFace), + offset = adjacentFace.oppositeFace + )) + } + + return filterPositionData(nodes, backwards) + } + /** * Filters the found adjacent nodes, after checking for transport possibility **/ @@ -54,6 +83,9 @@ interface Node { data class NodePositionData(val type: Node, val world: World, val position: BlockKey, val offset: BlockFace) { fun getNextNodes(cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, filter: ((Node, BlockFace) -> Boolean)?): List = type.getNextNodes(world, position, offset.oppositeFace, cachedNodeProvider, filter) + + fun getPreviousNodes(cachedNodeProvider: (CacheType, World, BlockKey) -> Node?, filter: ((Node, BlockFace) -> Boolean)?): List = + type.getPreviousNodes(world, position, offset.oppositeFace, cachedNodeProvider, filter) } fun onInvalidate() {} From 341d737c7de921bd671dab08b7f360e454236b3b Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Mon, 27 Jan 2025 12:36:22 -0600 Subject: [PATCH 435/500] Ignore cached paths for items, pending compound path keys --- .../features/transport/items/SortingOrder.kt | 4 +-- .../extractors/data/ItemExtractorData.kt | 30 ++++++++++++++++++- .../nodes/cache/FluidTransportCache.kt | 2 +- .../nodes/cache/ItemTransportCache.kt | 12 +++++--- .../nodes/cache/PowerTransportCache.kt | 2 +- .../transport/nodes/cache/TransportCache.kt | 13 +++++--- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt index 9ddcf3c808..6c3defa992 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt @@ -14,10 +14,10 @@ enum class SortingOrder { }, ROUND_ROBIN { override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { - val currentIndex = extractorData.roundRobinIndex + val currentIndex = extractorData.roundRobinIndex.toInt() val nextIndex = (currentIndex + 1) % destinations.size - extractorData.roundRobinIndex = nextIndex + extractorData.roundRobinIndex = nextIndex.toUShort() return destinations[nextIndex] } }, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt index abbc0cdecd..3436932bfc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/data/ItemExtractorData.kt @@ -1,9 +1,11 @@ package net.horizonsend.ion.server.features.transport.manager.extractors.data +import it.unimi.dsi.fastutil.ints.Int2IntRBTreeMap import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext import org.bukkit.persistence.PersistentDataContainer import org.bukkit.persistence.PersistentDataType @@ -15,13 +17,39 @@ class ItemExtractorData(pos: BlockKey, metaData: ItemExtractorMetaData) : Advanc override val key: BlockKey, var sortingOrder: SortingOrder = SortingOrder.NEAREST_FIRST ) : ExtractorMetaData { - var roundRobinIndex = 0 + /** Store an index for */ + var roundRobinIndex: UShort = 0.toUShort() + + private val pathCountLock = Any() + + private val itemPathCounts: MutableMap = Int2IntRBTreeMap() + + fun markItemPathfind(item: ItemStack) { + require(item.amount == 1) + val hash = item.hashCode() + + synchronized(pathCountLock) { + val current = itemPathCounts.getOrPut(hash) { 0 } + itemPathCounts[hash] = current + 1 + } + } + + fun getPathfindWeight(item: ItemStack) { + require(item.amount == 1) + val hash = item.hashCode() + + return synchronized(pathCountLock) { + itemPathCounts.getOrDefault(hash, 0) + } + } override fun toExtractorData(): ExtractorData { return ItemExtractorData(key, this) } companion object : PDCSerializers.RegisteredSerializer("ITEM_EXTRACTOR_METADATA", ItemExtractorMetaData::class) { + private const val ACCULULATED_PATHFIND_WEIGHTS = 30 + override fun toPrimitive( complex: ItemExtractorMetaData, context: PersistentDataAdapterContext, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 925bcb0aa1..23be0c3032 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -102,7 +102,7 @@ class FluidTransportCache(holder: CacheHolder): TransportCa val numDestinations = filteredDestinations.size val paths: Array = Array(numDestinations) { - getOrCachePath(source, filteredDestinations[it]) { node, _ -> + findPath(source, filteredDestinations[it]) { node, _ -> (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) != false) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 8a8c3c1c3e..1e68f48cf9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -112,16 +112,17 @@ class ItemTransportCache(holder: CacheHolder): TransportCach val numDestinations = destinations.size val paths: Array = measureOrFallback(TransportDebugCommand.pathfindTimes) { Array(numDestinations) { - getOrCachePath( - Node.NodePositionData( + findPath( + origin = Node.NodePositionData( ItemNode.ItemExtractorNode, holder.getWorld(), location, BlockFace.SELF ), - destinations[it] + destination = destinations[it], + ignoreCache = true // TODO wait for a caching implementation that will allow compound keys for item types ) { node, blockFace -> - if (node !is ItemNode.FilterNode) return@getOrCachePath true + if (node !is ItemNode.FilterNode) return@findPath true debugAudience.serverError("checking filter") node.matches(item) } @@ -134,8 +135,11 @@ class ItemTransportCache(holder: CacheHolder): TransportCach if (validDestinations.isEmpty()) { debugAudience.serverError("Could not find valid destination.") println(paths.toList()) + return } + meta?.markItemPathfind(item) + val destination = if (meta != null) { distributionOrder.getDestination(meta, validDestinations) } else { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index b9bc10a50c..4a7ee666dc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -141,7 +141,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val numDestinations = filteredDestinations.size val paths: Array = measureOrFallback(TransportDebugCommand.pathfindTimes) { Array(numDestinations) { - getOrCachePath(source, filteredDestinations[it]) + findPath(source, filteredDestinations[it]) } } var maximumResistance: Double = -1.0 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index c34c133311..e57227c6e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -252,15 +252,20 @@ abstract class TransportCache(val holder: CacheHolder<*>) { } } - fun getOrCachePath(origin: Node.NodePositionData, destination: BlockKey, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): PathfindingReport? { - if (pathCache.contains(origin.position, destination)) { + fun findPath( + origin: Node.NodePositionData, + destination: BlockKey, + ignoreCache: Boolean = false, + pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null + ): PathfindingReport? { + if (!ignoreCache && pathCache.contains(origin.position, destination)) { return synchronized(pathCacheLock) { pathCache.get(origin.position, destination)?.getOrNull() } } val path = runCatching { getIdealPath(origin, destination, holder.nodeProvider, pathfindingFilter) }.getOrNull() if (path == null) { - synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.empty() } + if (!ignoreCache) synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.empty() } return null } @@ -268,7 +273,7 @@ abstract class TransportCache(val holder: CacheHolder<*>) { val report = PathfindingReport(path, resistance) - synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.of(report) } + if (!ignoreCache) synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.of(report) } return report } From 28bc9cf240b771aefb3877dac15db7fb8fc5d437 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Mon, 27 Jan 2025 13:20:38 -0600 Subject: [PATCH 436/500] bare minimum Item transaction --- .../nodes/cache/ItemTransportCache.kt | 32 +++++- .../transport/util/ItemTransaction.kt | 103 ++++++++++++++++++ 2 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 1e68f48cf9..241257b66d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -15,11 +15,14 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.ItemTransaction import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.minecraft @@ -28,6 +31,7 @@ import net.minecraft.world.Container import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.block.BlockFace +import org.bukkit.block.BlockState import org.bukkit.block.data.type.CommandBlock import org.bukkit.block.data.type.Hopper import org.bukkit.craftbukkit.block.impl.CraftGrindstone @@ -128,8 +132,12 @@ class ItemTransportCache(holder: CacheHolder): TransportCach } } } - val validDestinations = destinations.filterIndexed { index, _ -> - paths[index] != null + var destinationMap = mutableMapOf() + + val validDestinations = destinations.filterIndexed { index, destination -> + val path = paths[index] + path?.let { destinationMap[destination] = index } + path != null } if (validDestinations.isEmpty()) { @@ -147,12 +155,28 @@ class ItemTransportCache(holder: CacheHolder): TransportCach destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } } + val path = destinationMap[destination]!! + + val transact = ItemTransaction(holder as CacheHolder, { stack1, stack2 -> + stack1.isSimilar(stack2) //TODO + }) + + for (source in sources) { + val key = toBlockKey(Vec3i((source.holder as BlockState).location)) + + transact.addRemoval(key, ItemTransaction.ItemDiff(item, -count)) + } + + transact.addAddition(destination, ItemTransaction.ItemDiff(item, count)) + + transact.commit() + debugAudience.highlightBlock(toVec3i(destination), 40L) } } - fun getInventory(key: BlockKey): Inventory? { - val globalVec = holder.transportManager.getGlobalCoordinate(toVec3i(key)) + fun getInventory(localKey: BlockKey): Inventory? { + val globalVec = holder.transportManager.getGlobalCoordinate(toVec3i(localKey)) val nmsChunk = holder.getWorld().minecraft.getChunkIfLoaded(globalVec.x.shr(4), globalVec.z.shr(4)) ?: return null val tileEntity = nmsChunk.getBlockEntity(BlockPos(globalVec.x, globalVec.y, globalVec.z)) as? Container ?: return null diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt new file mode 100644 index 0000000000..fdd1bd5d31 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt @@ -0,0 +1,103 @@ +package net.horizonsend.ion.server.features.transport.util + +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache +import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf +import org.bukkit.inventory.ItemStack +import kotlin.math.abs + +class ItemTransaction(val originCacheHolder: CacheHolder, val similarityProvider: (ItemStack, ItemStack) -> Boolean) { + data class ItemDiff(val item: ItemStack, val amount: Int) + val removes = multimapOf() + val adds = multimapOf() + + fun addRemoval(sourcePos: BlockKey, diff: ItemDiff) { + removes[sourcePos].add(diff) + } + + fun addAddition(sourcePos: BlockKey, diff: ItemDiff) { + adds[sourcePos].add(diff) + } + + /** + * Commits the item difference + * Returns if the commit was successful + **/ + fun commitItemDiff(localKey: BlockKey, diff: ItemDiff): Boolean { + val inventory = originCacheHolder.cache.getInventory(localKey) ?: return false + + // If remove + if (diff.amount < 0) { + val byCount = mutableMapOf() + val contents = inventory.contents.filterNotNull() + + for (item in contents) { + val asOne = item.asOne() + if (byCount.containsKey(asOne)) continue + val count = contents.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } + byCount[asOne] = count + } + + val toRemove = abs(diff.amount) + + if (byCount.getOrDefault(diff.item, 0) <= toRemove) return false + + var remaining = toRemove + + var iterations = 0 + // Upper bound of inventory as double chest size + while (remaining > 0 && iterations < 54) { + iterations++ + val item = contents.first { stack -> similarityProvider(stack, diff.item) } + val amount = item.amount + + val toRemove = minOf(amount, remaining) + + remaining -= toRemove + item.amount -= toRemove + } + + return true + } + + // If add + if (!LegacyItemUtils.canFit(inventory, diff.item, diff.amount)) { + return false + } + + val stacks = mutableListOf() + + var remaining = diff.amount + var iterations = 0 + while (remaining > 0 && iterations < 54) { + iterations++ + + val maxStackSize = diff.item.maxStackSize + val newAmount = minOf(maxStackSize, remaining) + remaining -= newAmount + stacks.add(diff.item.asQuantity(newAmount)) + } + + stacks.forEach(inventory::addItem) + + return true + } + + fun commit() { + for (key in removes.keys()) { + val diffs = removes[key] + for (diff in diffs) { + if (commitItemDiff(key, diff)) return + } + } + + for (key in adds.keys()) { + val diffs = adds[key] + for (diff in diffs) { + if (commitItemDiff(key, diff)) return + } + } + } +} From d4c81a44eb1a81f89c221bd088371204f960c544 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 28 Jan 2025 08:50:38 -0600 Subject: [PATCH 437/500] build better transaction code --- .../nodes/cache/ItemTransportCache.kt | 2 +- .../transport/util/ItemTransaction.kt | 103 ------------------ .../transport/util/transaction/Change.kt | 80 ++++++++++++++ .../util/transaction/ItemTransaction.kt | 63 +++++++++++ 4 files changed, 144 insertions(+), 104 deletions(-) delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 241257b66d..a0108ed395 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -15,7 +15,7 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.ItemTransaction +import net.horizonsend.ion.server.features.transport.util.transaction.ItemTransaction import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt deleted file mode 100644 index fdd1bd5d31..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/ItemTransaction.kt +++ /dev/null @@ -1,103 +0,0 @@ -package net.horizonsend.ion.server.features.transport.util - -import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder -import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache -import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.multimapOf -import org.bukkit.inventory.ItemStack -import kotlin.math.abs - -class ItemTransaction(val originCacheHolder: CacheHolder, val similarityProvider: (ItemStack, ItemStack) -> Boolean) { - data class ItemDiff(val item: ItemStack, val amount: Int) - val removes = multimapOf() - val adds = multimapOf() - - fun addRemoval(sourcePos: BlockKey, diff: ItemDiff) { - removes[sourcePos].add(diff) - } - - fun addAddition(sourcePos: BlockKey, diff: ItemDiff) { - adds[sourcePos].add(diff) - } - - /** - * Commits the item difference - * Returns if the commit was successful - **/ - fun commitItemDiff(localKey: BlockKey, diff: ItemDiff): Boolean { - val inventory = originCacheHolder.cache.getInventory(localKey) ?: return false - - // If remove - if (diff.amount < 0) { - val byCount = mutableMapOf() - val contents = inventory.contents.filterNotNull() - - for (item in contents) { - val asOne = item.asOne() - if (byCount.containsKey(asOne)) continue - val count = contents.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } - byCount[asOne] = count - } - - val toRemove = abs(diff.amount) - - if (byCount.getOrDefault(diff.item, 0) <= toRemove) return false - - var remaining = toRemove - - var iterations = 0 - // Upper bound of inventory as double chest size - while (remaining > 0 && iterations < 54) { - iterations++ - val item = contents.first { stack -> similarityProvider(stack, diff.item) } - val amount = item.amount - - val toRemove = minOf(amount, remaining) - - remaining -= toRemove - item.amount -= toRemove - } - - return true - } - - // If add - if (!LegacyItemUtils.canFit(inventory, diff.item, diff.amount)) { - return false - } - - val stacks = mutableListOf() - - var remaining = diff.amount - var iterations = 0 - while (remaining > 0 && iterations < 54) { - iterations++ - - val maxStackSize = diff.item.maxStackSize - val newAmount = minOf(maxStackSize, remaining) - remaining -= newAmount - stacks.add(diff.item.asQuantity(newAmount)) - } - - stacks.forEach(inventory::addItem) - - return true - } - - fun commit() { - for (key in removes.keys()) { - val diffs = removes[key] - for (diff in diffs) { - if (commitItemDiff(key, diff)) return - } - } - - for (key in adds.keys()) { - val diffs = adds[key] - for (diff in diffs) { - if (commitItemDiff(key, diff)) return - } - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt new file mode 100644 index 0000000000..3d8d3d91e0 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt @@ -0,0 +1,80 @@ +package net.horizonsend.ion.server.features.transport.util.transaction + +import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack +import kotlin.math.abs + +interface Change { + fun check(inventory: Inventory): Boolean + + fun execute(inventory: Inventory): Boolean + + class ItemRemoval(val item: ItemStack, val amount: Int, val similarityProvider: (ItemStack, ItemStack) -> Boolean) : Change { + override fun check(inventory: Inventory): Boolean { + TODO("Not yet implemented") + } + + override fun execute(inventory: Inventory): Boolean { + val byCount = mutableMapOf() + val contents = inventory.contents.filterNotNull() + + for (item in contents) { + val asOne = item.asOne() + if (byCount.containsKey(asOne)) continue + val count = contents.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } + byCount[asOne] = count + } + + val toRemove = abs(amount) + + if (byCount.getOrDefault(item, 0) <= toRemove) return false + + var remaining = toRemove + + var iterations = 0 + // Upper bound of inventory as double chest size + while (remaining > 0 && iterations < 54) { + iterations++ + val item = contents.first { stack -> similarityProvider(stack, item) } + val amount = item.amount + + val toRemove = minOf(amount, remaining) + + remaining -= toRemove + item.amount -= toRemove + } + + return true + } + } + + class ItemAddition(val item: ItemStack, val amount: Int) : Change { + override fun check(inventory: Inventory): Boolean { + TODO("Not yet implemented") + } + + override fun execute(inventory: Inventory): Boolean { + if (!LegacyItemUtils.canFit(inventory, item, amount)) { + return false + } + + val stacks = mutableListOf() + + var remaining = amount + var iterations = 0 + while (remaining > 0 && iterations < 54) { + iterations++ + + val maxStackSize = item.maxStackSize + val newAmount = minOf(maxStackSize, remaining) + remaining -= newAmount + stacks.add(item.asQuantity(newAmount)) + } + + stacks.forEach(inventory::addItem) + + return true + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt new file mode 100644 index 0000000000..d90070bab4 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt @@ -0,0 +1,63 @@ +package net.horizonsend.ion.server.features.transport.util.transaction + +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache +import net.horizonsend.ion.server.features.transport.util.transaction.Change.ItemAddition +import net.horizonsend.ion.server.features.transport.util.transaction.Change.ItemRemoval +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf +import org.bukkit.inventory.Inventory + +class ItemTransaction(val originCacheHolder: CacheHolder) { + val removals = multimapOf() + val additions = multimapOf() + + fun addRemoval(sourcePos: BlockKey, diff: ItemRemoval) { + removals[sourcePos].add(diff) + } + + fun addAddition(sourcePos: BlockKey, diff: ItemAddition) { + additions[sourcePos].add(diff) + } + + data class CommitContext(val key: BlockKey, val inventory: Inventory, val change: Change) { + fun check() = change.check(inventory) + fun commit() = change.execute(inventory) + } + + fun commit() { + val inventories = mutableMapOf() + + val removalContexts = mutableListOf() + val additionContexts = mutableListOf() + + val getInventory = fun(key: BlockKey): Inventory? { + return inventories.getOrPut(key) { originCacheHolder.cache.getInventory(key) } + } + + removals.entries().mapNotNullTo(removalContexts) { entry -> + val inventory = getInventory(entry.key) ?: return@mapNotNullTo null + CommitContext(entry.key, inventory, entry.value) + } + + additions.entries().mapNotNullTo(additionContexts) { entry -> + val inventory = getInventory(entry.key) ?: return@mapNotNullTo null + CommitContext(entry.key, inventory, entry.value) + } + + if (!checkAll(removalContexts)) return + if (!checkAll(additionContexts)) return + + for (removal in removalContexts) { + removal.commit() + } + + for (addition in additionContexts) { + addition.commit() + } + } + + fun checkAll(contexts: Collection): Boolean { + return contexts.all { context -> context.check() } + } +} From 525e2d5242e930b06b78ac8bf8f8fe3f8499c30e Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:17:21 -0600 Subject: [PATCH 438/500] non-silent exception handling, some other fixes and improvements --- .../command/misc/TransportDebugCommand.kt | 2 +- .../gui/custom/filter/ItemFilterGui.kt | 2 +- .../server/features/transport/NewTransport.kt | 15 ++++++- .../features/transport/filters/FilterType.kt | 3 +- .../nodes/cache/FluidTransportCache.kt | 10 ++--- .../nodes/cache/ItemTransportCache.kt | 42 ++++++++++++------- .../nodes/cache/PowerTransportCache.kt | 4 +- .../transport/nodes/cache/TransportCache.kt | 2 +- .../transport/util/transaction/Change.kt | 8 +--- .../miscellaneous/registrations/Components.kt | 2 + 10 files changed, 55 insertions(+), 35 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 9ea80bfbf7..f9279ada41 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -212,7 +212,7 @@ object TransportDebugCommand : SLCommand() { sender.highlightBlocks(destinations.map(::toVec3i), 50L) } - const val COLLECT_TRANSPORT_METRICS = true + const val COLLECT_TRANSPORT_METRICS = false val floodFillTimes = LinkedBlockingDeque(10_000) val solarFloodFillTimes = LinkedBlockingDeque(10_000) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt index f664c5b703..377f4380bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -93,7 +93,7 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData>() - lateinit var monitorThread: Timer - lateinit var executor: ExecutorService + private lateinit var monitorThread: Timer + private lateinit var executor: ExecutorService override fun onEnable() { executor = Executors.newFixedThreadPool(64, Tasks.namedThreadFactory("wire-transport")) @@ -58,6 +58,17 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t saveExtractors() } + fun runTask(task: () -> Unit) { + executor.execute { + try { + task.invoke() + } catch (e: Throwable) { + log.error("Encountered exception when executing async transport task: ${e.message}") + e.printStackTrace() + } + } + } + fun registerTransportManager(manager: TransportManager<*>) { transportManagers.add(manager) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index 9be2c840e2..5bcb884f15 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.filters import net.horizonsend.ion.common.utils.text.toComponent +import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.transport.filters.FilterMeta.EmptyFilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.fluids.Fluid @@ -109,7 +110,7 @@ abstract class FilterType( } } - companion object { + companion object : IonServerComponent() { private val byId = mapOf("FLUID" to FluidType, "ITEMS" to ItemType) operator fun get(identifier: String): FilterType<*, *> = byId[identifier] ?: throw NoSuchElementException("Filter type $identifier not found") diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 23be0c3032..8b9aa56b5e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -44,21 +44,21 @@ class FluidTransportCache(holder: CacheHolder): TransportCa .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) .build() - override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { NewTransport.executor.submit { + override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { NewTransport.runTask { val world = holder.getWorld() val sources = getExtractorSourceEntities(location) { it.isEmpty() } - val source = sources.randomOrNull() ?: return@submit //TODO take from all + val source = sources.randomOrNull() ?: return@runTask //TODO take from all - if (source.getStoredResources().isEmpty()) return@submit + if (source.getStoredResources().isEmpty()) return@runTask - val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), location) ?: return@submit + val originNode = holder.nodeProvider.invoke(type, holder.getWorld(), location) ?: return@runTask // Flood fill on the network to find power inputs, and check input data for multiblocks using that input that can store any power val destinations: Collection = getNetworkDestinations(location, originNode) { node -> world.ion.inputManager.getHolders(type, node.position).any { entity -> entity is FluidStoringEntity && !entity.isFull() } } - if (destinations.isEmpty()) return@submit + if (destinations.isEmpty()) return@runTask val transferLimit = (transportSettings().extractorConfiguration.maxFluidRemovedPerExtractorTick * delta).roundToInt() val resources = source.getExtractableResources() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index a0108ed395..dbb63ab747 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -15,12 +15,13 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.transaction.Change import net.horizonsend.ion.server.features.transport.util.transaction.ItemTransaction import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES +import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i @@ -28,19 +29,18 @@ import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.minecraft import net.minecraft.core.BlockPos import net.minecraft.world.Container +import net.minecraft.world.level.block.entity.BlockEntity import org.bukkit.Material import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.block.BlockFace -import org.bukkit.block.BlockState import org.bukkit.block.data.type.CommandBlock import org.bukkit.block.data.type.Hopper import org.bukkit.craftbukkit.block.impl.CraftGrindstone import org.bukkit.craftbukkit.inventory.CraftInventory -import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass -class ItemTransportCache(holder: CacheHolder): TransportCache(holder) { +class ItemTransportCache(override val holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.ITEMS override val extractorNodeClass: KClass = ItemNode.ItemExtractorNode::class override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() @@ -70,7 +70,7 @@ class ItemTransportCache(holder: CacheHolder): TransportCach delta: Double, metaData: ExtractorMetaData?, ) { - NewTransport.executor.submit { + NewTransport.runTask { measureOrFallback(TransportDebugCommand.extractorTickTimes) { handleExtractorTick(location, delta, metaData as? ItemExtractorMetaData) } @@ -105,7 +105,7 @@ class ItemTransportCache(holder: CacheHolder): TransportCach debugAudience.information("Checking ${item.type} [$count]") val destinations: List = getNetworkDestinations(location, originNode) { node -> val inventory = getInventory(node.position) - inventory != null && inventory.isEmpty //TODO full + inventory != null && LegacyItemUtils.canFit(inventory, item, 1) }.toList() if (destinations.isEmpty()) { @@ -128,7 +128,7 @@ class ItemTransportCache(holder: CacheHolder): TransportCach ) { node, blockFace -> if (node !is ItemNode.FilterNode) return@findPath true debugAudience.serverError("checking filter") - node.matches(item) + node.matches(item).apply { debugAudience.serverError("filter returned $this") } } } } @@ -155,27 +155,37 @@ class ItemTransportCache(holder: CacheHolder): TransportCach destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } } - val path = destinationMap[destination]!! + debugAudience.information("Selected destination ${toVec3i(destination)}") - val transact = ItemTransaction(holder as CacheHolder, { stack1, stack2 -> +// val path = destinationMap[destination]!! + val diffProvider = { stack1: ItemStack, stack2: ItemStack -> stack1.isSimilar(stack2) //TODO - }) + } + debugAudience.information("1") + + val transact = ItemTransaction(holder) + debugAudience.information("2") for (source in sources) { - val key = toBlockKey(Vec3i((source.holder as BlockState).location)) + println("source holder: ${source.inventory}") + val key = toBlockKey((source.inventory as BlockEntity).blockPos.toVec3i()) + debugAudience.information("3 ${toVec3i(key)}") - transact.addRemoval(key, ItemTransaction.ItemDiff(item, -count)) + transact.addRemoval(key, Change.ItemRemoval(item, count, diffProvider)) } + debugAudience.information("4") - transact.addAddition(destination, ItemTransaction.ItemDiff(item, count)) + transact.addAddition(destination, Change.ItemAddition(item, count)) + debugAudience.information("Committing transaction") transact.commit() + debugAudience.information("Finished transaction") debugAudience.highlightBlock(toVec3i(destination), 40L) } } - fun getInventory(localKey: BlockKey): Inventory? { + fun getInventory(localKey: BlockKey): CraftInventory? { val globalVec = holder.transportManager.getGlobalCoordinate(toVec3i(localKey)) val nmsChunk = holder.getWorld().minecraft.getChunkIfLoaded(globalVec.x.shr(4), globalVec.z.shr(4)) ?: return null val tileEntity = nmsChunk.getBlockEntity(BlockPos(globalVec.x, globalVec.y, globalVec.z)) as? Container ?: return null @@ -183,8 +193,8 @@ class ItemTransportCache(holder: CacheHolder): TransportCach return CraftInventory(tileEntity) } - fun getSources(extractorLocation: BlockKey): Set { - val inventories = mutableSetOf() + fun getSources(extractorLocation: BlockKey): Set { + val inventories = mutableSetOf() for (face in ADJACENT_BLOCK_FACES) { val inventoryLocation = getRelative(extractorLocation, face) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 4a7ee666dc..91da918079 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -50,7 +50,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC tickPowerExtractor(location, delta) } - private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.executor.submit { + private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.runTask { measureOrFallback(TransportDebugCommand.extractorTickTimes) { val world = holder.getWorld() @@ -95,7 +95,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC } } - private fun tickSolarPanel(location: BlockKey, delta: Double, solarCache: SolarPanelCache) = NewTransport.executor.submit { + private fun tickSolarPanel(location: BlockKey, delta: Double, solarCache: SolarPanelCache) = NewTransport.runTask { measureOrFallback(TransportDebugCommand.solarTickTimes) { val transportPower = solarCache.getPower(holder.getWorld(), location, delta) if (transportPower == 0) return@measureOrFallback diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index e57227c6e3..45ee471310 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -33,7 +33,7 @@ import java.util.concurrent.ConcurrentHashMap import kotlin.jvm.optionals.getOrNull import kotlin.reflect.KClass -abstract class TransportCache(val holder: CacheHolder<*>) { +abstract class TransportCache(open val holder: CacheHolder<*>) { /** * Cache containing a cache state at their corresponding block position. * The state can either be empty, or present. Empty key / value pairs have not been cached. diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt index 3d8d3d91e0..276f8c9416 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt @@ -12,7 +12,7 @@ interface Change { class ItemRemoval(val item: ItemStack, val amount: Int, val similarityProvider: (ItemStack, ItemStack) -> Boolean) : Change { override fun check(inventory: Inventory): Boolean { - TODO("Not yet implemented") + return true //TODO } override fun execute(inventory: Inventory): Boolean { @@ -51,14 +51,10 @@ interface Change { class ItemAddition(val item: ItemStack, val amount: Int) : Change { override fun check(inventory: Inventory): Boolean { - TODO("Not yet implemented") + return LegacyItemUtils.canFit(inventory, item, amount) //TODO } override fun execute(inventory: Inventory): Boolean { - if (!LegacyItemUtils.canFit(inventory, item, amount)) { - return false - } - val stacks = mutableListOf() var remaining = amount diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt index eb31313733..f41dabe57a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/Components.kt @@ -88,6 +88,7 @@ import net.horizonsend.ion.server.features.starship.hyperspace.HyperspaceBeacons import net.horizonsend.ion.server.features.starship.movement.PlanetTeleportCooldown import net.horizonsend.ion.server.features.starship.subsystem.shield.StarshipShields import net.horizonsend.ion.server.features.transport.NewTransport +import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.fluids.FluidRegistry import net.horizonsend.ion.server.features.transport.old.TransportConfig import net.horizonsend.ion.server.features.transport.old.Wires @@ -144,6 +145,7 @@ val components: List = listOf( TransportConfig.Companion, Pipes, + FilterType, Filters, Wires, NewTransport, From aa617628d7541bb00e8fef6e2d7f3e7b51756752 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:19:00 -0600 Subject: [PATCH 439/500] move transaction to item --- .../transport/{util => items}/transaction/Change.kt | 2 +- .../{util => items}/transaction/ItemTransaction.kt | 6 +++--- .../transport/nodes/cache/ItemTransportCache.kt | 11 +++-------- 3 files changed, 7 insertions(+), 12 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{util => items}/transaction/Change.kt (96%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/transport/{util => items}/transaction/ItemTransaction.kt (88%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt similarity index 96% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt index 276f8c9416..a5cf457ba1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/Change.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.transport.util.transaction +package net.horizonsend.ion.server.features.transport.items.transaction import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt similarity index 88% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt index d90070bab4..83239699d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/transaction/ItemTransaction.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt @@ -1,9 +1,9 @@ -package net.horizonsend.ion.server.features.transport.util.transaction +package net.horizonsend.ion.server.features.transport.items.transaction +import net.horizonsend.ion.server.features.transport.items.transaction.Change.ItemAddition +import net.horizonsend.ion.server.features.transport.items.transaction.Change.ItemRemoval import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache -import net.horizonsend.ion.server.features.transport.util.transaction.Change.ItemAddition -import net.horizonsend.ion.server.features.transport.util.transaction.Change.ItemRemoval import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import org.bukkit.inventory.Inventory diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index dbb63ab747..b431367531 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -8,6 +8,8 @@ import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities. import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.items.SortingOrder +import net.horizonsend.ion.server.features.transport.items.transaction.Change +import net.horizonsend.ion.server.features.transport.items.transaction.ItemTransaction import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder @@ -15,8 +17,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.transaction.Change -import net.horizonsend.ion.server.features.transport.util.transaction.ItemTransaction import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES @@ -128,7 +128,7 @@ class ItemTransportCache(override val holder: CacheHolder): ) { node, blockFace -> if (node !is ItemNode.FilterNode) return@findPath true debugAudience.serverError("checking filter") - node.matches(item).apply { debugAudience.serverError("filter returned $this") } + node.matches(item) } } } @@ -161,10 +161,8 @@ class ItemTransportCache(override val holder: CacheHolder): val diffProvider = { stack1: ItemStack, stack2: ItemStack -> stack1.isSimilar(stack2) //TODO } - debugAudience.information("1") val transact = ItemTransaction(holder) - debugAudience.information("2") for (source in sources) { println("source holder: ${source.inventory}") @@ -173,13 +171,10 @@ class ItemTransportCache(override val holder: CacheHolder): transact.addRemoval(key, Change.ItemRemoval(item, count, diffProvider)) } - debugAudience.information("4") transact.addAddition(destination, Change.ItemAddition(item, count)) - debugAudience.information("Committing transaction") transact.commit() - debugAudience.information("Finished transaction") debugAudience.highlightBlock(toVec3i(destination), 40L) } From 7bde031c03d3247118eec74e10575f149495a2be Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:58:03 -0600 Subject: [PATCH 440/500] Fix item removal --- .../transport/items/transaction/Change.kt | 15 ++++++++++----- .../transport/nodes/cache/ItemTransportCache.kt | 17 ++++------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt index a5cf457ba1..736bc12015 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt @@ -10,7 +10,7 @@ interface Change { fun execute(inventory: Inventory): Boolean - class ItemRemoval(val item: ItemStack, val amount: Int, val similarityProvider: (ItemStack, ItemStack) -> Boolean) : Change { + class ItemRemoval(val item: ItemStack, val amount: Int) : Change { override fun check(inventory: Inventory): Boolean { return true //TODO } @@ -28,7 +28,7 @@ interface Change { val toRemove = abs(amount) - if (byCount.getOrDefault(item, 0) <= toRemove) return false + if (byCount.getOrDefault(item, 0) < toRemove) return false var remaining = toRemove @@ -36,13 +36,18 @@ interface Change { // Upper bound of inventory as double chest size while (remaining > 0 && iterations < 54) { iterations++ - val item = contents.first { stack -> similarityProvider(stack, item) } - val amount = item.amount + val invItem = contents.first { stack -> stack.isSimilar(item) } + val amount = invItem.amount val toRemove = minOf(amount, remaining) remaining -= toRemove - item.amount -= toRemove + + if (toRemove == invItem.maxStackSize) { + inventory.remove(invItem) + } + + invItem.amount -= toRemove } return true diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index b431367531..f27df104f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -103,6 +103,7 @@ class ItemTransportCache(override val holder: CacheHolder): for ((item, count) in byCount) { debugAudience.information("Checking ${item.type} [$count]") + val destinations: List = getNetworkDestinations(location, originNode) { node -> val inventory = getInventory(node.position) inventory != null && LegacyItemUtils.canFit(inventory, item, 1) @@ -132,17 +133,15 @@ class ItemTransportCache(override val holder: CacheHolder): } } } - var destinationMap = mutableMapOf() +// var destinationMap = mutableMapOf() val validDestinations = destinations.filterIndexed { index, destination -> val path = paths[index] - path?.let { destinationMap[destination] = index } +// path?.let { destinationMap[destination] = index } path != null } if (validDestinations.isEmpty()) { - debugAudience.serverError("Could not find valid destination.") - println(paths.toList()) return } @@ -157,19 +156,11 @@ class ItemTransportCache(override val holder: CacheHolder): debugAudience.information("Selected destination ${toVec3i(destination)}") -// val path = destinationMap[destination]!! - val diffProvider = { stack1: ItemStack, stack2: ItemStack -> - stack1.isSimilar(stack2) //TODO - } - val transact = ItemTransaction(holder) for (source in sources) { - println("source holder: ${source.inventory}") val key = toBlockKey((source.inventory as BlockEntity).blockPos.toVec3i()) - debugAudience.information("3 ${toVec3i(key)}") - - transact.addRemoval(key, Change.ItemRemoval(item, count, diffProvider)) + transact.addRemoval(key, Change.ItemRemoval(item, count)) } transact.addAddition(destination, Change.ItemAddition(item, count)) From 547694e4511e8c5cd226b929673bd12dc48782eb Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 29 Jan 2025 13:38:44 -0600 Subject: [PATCH 441/500] store chunk filters, load from stored data if not present --- .../features/client/display/HudIcons.kt | 13 +++------- .../filters/manager/ChunkFilterManager.kt | 24 ++++++++++++++++--- .../filters/manager/FilterManager.kt | 23 +++++++++++++++--- .../nodes/cache/ItemTransportCache.kt | 8 ++----- .../features/transport/util/TransportUtils.kt | 24 +++++++++++++++++++ .../persistence/NamespacedKeys.kt | 1 + 6 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/TransportUtils.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/HudIcons.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/HudIcons.kt index 15ab8c9d91..fd0d256f67 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/HudIcons.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/HudIcons.kt @@ -146,10 +146,7 @@ object HudIcons : IonServerComponent() { // remove entity if it is in an unloaded chunk or different world (this causes the entity client-side to despawn?) // also do not render if the planet is closer than the entity render distance - if (!nmsEntity.isChunkLoaded || - nmsEntity.level().world.name != player.world.name || - visualDistance < entityRenderDistance * 2 - ) { + if (nmsEntity.level().world.name != player.world.name || visualDistance < entityRenderDistance * 2) { ClientDisplayEntities.deleteDisplayEntityPacket(player, nmsEntity) ClientDisplayEntities[player.uniqueId]?.remove(identifier) return @@ -251,9 +248,7 @@ object HudIcons : IonServerComponent() { // remove entity if it is in an unloaded chunk or different world (this causes the entity client-side to despawn?) // also do not render if the planet is closer than the entity render distance - if (!nmsEntity.isChunkLoaded || - nmsEntity.level().world.name != player.world.name - ) { + if (nmsEntity.level().world.name != player.world.name) { ClientDisplayEntities.deleteDisplayEntityPacket(player, nmsEntity) ClientDisplayEntities[player.uniqueId]?.remove(SELECTOR_ID) return @@ -353,9 +348,7 @@ object HudIcons : IonServerComponent() { // remove entity if it is in an unloaded chunk or different world (this causes the entity client-side to despawn?) // also do not render if the planet is closer than the entity render distance - if (!nmsEntity.isChunkLoaded || - nmsEntity.level().world.name != player.world.name - ) { + if (nmsEntity.level().world.name != player.world.name) { ClientDisplayEntities.deleteDisplayEntityPacket(player, nmsEntity) ClientDisplayEntities[player.uniqueId]?.remove(SELECTOR_TEXT_ID) return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt index 4d045a3874..941a83c321 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/ChunkFilterManager.kt @@ -1,13 +1,31 @@ package net.horizonsend.ion.server.features.transport.filters.manager +import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.manager.ChunkTransportManager +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import org.bukkit.persistence.PersistentDataContainer +import org.bukkit.persistence.PersistentDataType -class ChunkFilterManager(manager: ChunkTransportManager) : FilterManager(manager) { +class ChunkFilterManager(override val manager: ChunkTransportManager) : FilterManager(manager) { override fun save() { - TODO("Not yet implemented") + val pdc = manager.chunk.inner.persistentDataContainer + + val filterData = mutableListOf() + + for (entry in filters.values) { + filterData.add(FilterData.toPrimitive(entry, pdc.adapterContext)) + } + + pdc.set(NamespacedKeys.CHUNK_FILTER_DATA, PersistentDataType.LIST.dataContainers(), filterData) } override fun load() { - TODO("Not yet implemented") + val pdc = manager.chunk.inner.persistentDataContainer + val stored = pdc.getOrDefault(NamespacedKeys.CHUNK_FILTER_DATA, PersistentDataType.LIST.dataContainers(), listOf()) + + for (data in stored) { + val filterData = FilterData.fromPrimitive(data, pdc.adapterContext) + filters[filterData.position] = filterData + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt index 28c03a4f2c..10b987b0c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -6,13 +6,14 @@ import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.manager.TransportManager +import net.horizonsend.ion.server.features.transport.util.getPersistentDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import org.bukkit.block.CommandBlock -abstract class FilterManager(val manager: TransportManager<*>) { +abstract class FilterManager(open val manager: TransportManager<*>) { val filters = Long2ObjectOpenHashMap>() private val mutex = Any() @@ -28,11 +29,27 @@ abstract class FilterManager(val manager: TransportManager<*>) { } fun getFilter(key: BlockKey): FilterData<*, *>? { - return filters[key] + val saved = filters[key] + if (saved != null) return saved + + val pdc = getPersistentDataContainer(key, manager.getWorld()) ?: return null + + val entityStored = pdc.get(NamespacedKeys.FILTER_DATA, FilterData) + if (entityStored != null) { filters[toBlockKey(manager.getLocalCoordinate(toVec3i(key)))] = entityStored } + + return entityStored } fun getFilter(key: BlockKey, type: FilterType): FilterData? { - return filters[key]?.let { data -> type.cast(data) } + val saved = filters[key]?.let { data -> type.cast(data) } + if (saved != null) return saved + + val pdc = getPersistentDataContainer(key, manager.getWorld()) ?: return null + + val entityStored = pdc.get(NamespacedKeys.FILTER_DATA, FilterData)?.let { data -> type.cast(data) } + if (entityStored != null) { filters[toBlockKey(manager.getLocalCoordinate(toVec3i(key)))] = entityStored } + + return entityStored } fun addFilter(key: BlockKey, data: FilterData<*, *>) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index f27df104f4..e2f56f1490 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -17,6 +17,7 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.getBlockEntity import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES @@ -26,8 +27,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience -import net.horizonsend.ion.server.miscellaneous.utils.minecraft -import net.minecraft.core.BlockPos import net.minecraft.world.Container import net.minecraft.world.level.block.entity.BlockEntity import org.bukkit.Material @@ -172,10 +171,7 @@ class ItemTransportCache(override val holder: CacheHolder): } fun getInventory(localKey: BlockKey): CraftInventory? { - val globalVec = holder.transportManager.getGlobalCoordinate(toVec3i(localKey)) - val nmsChunk = holder.getWorld().minecraft.getChunkIfLoaded(globalVec.x.shr(4), globalVec.z.shr(4)) ?: return null - val tileEntity = nmsChunk.getBlockEntity(BlockPos(globalVec.x, globalVec.y, globalVec.z)) as? Container ?: return null - + val tileEntity = getBlockEntity(holder.transportManager.getGlobalCoordinate(toVec3i(localKey)), holder.getWorld()) as? Container ?: return null return CraftInventory(tileEntity) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/TransportUtils.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/TransportUtils.kt new file mode 100644 index 0000000000..16229d5cee --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/TransportUtils.kt @@ -0,0 +1,24 @@ +package net.horizonsend.ion.server.features.transport.util + +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.minecraft +import net.minecraft.core.BlockPos +import net.minecraft.world.level.block.entity.BlockEntity +import org.bukkit.World +import org.bukkit.persistence.PersistentDataContainer + +fun getBlockEntity(globalBlockKey: BlockKey, world: World): BlockEntity? { + val globalVec3i = toVec3i(globalBlockKey) + val nmsChunk = world.minecraft.getChunkIfLoaded(globalVec3i.x.shr(4), globalVec3i.z.shr(4)) ?: return null + return nmsChunk.getBlockEntity(BlockPos(globalVec3i.x, globalVec3i.y, globalVec3i.z)) +} + +fun getBlockEntity(globalVec3i: Vec3i, world: World): BlockEntity? { + val nmsChunk = world.minecraft.getChunkIfLoaded(globalVec3i.x.shr(4), globalVec3i.z.shr(4)) ?: return null + return nmsChunk.getBlockEntity(BlockPos(globalVec3i.x, globalVec3i.y, globalVec3i.z)) +} + +fun getPersistentDataContainer(globalBlockKey: BlockKey, world: World): PersistentDataContainer? = getBlockEntity(globalBlockKey, world)?.persistentDataContainer +fun getPersistentDataContainer(globalVec3i: Vec3i, world: World): PersistentDataContainer? = getBlockEntity(globalVec3i, world)?.persistentDataContainer diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index be82985e65..7e89cf6907 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -89,6 +89,7 @@ object NamespacedKeys { val SERIALIZATION_TYPE = key("serialization_type") val META_DATA = key("meta_data") + val CHUNK_FILTER_DATA = key("chunk_filter_data") val FILTER_DATA = key("filter_data") val FILTER_TYPE = key("filter_type") val FILTER_ENTRY = key("filter_entry") From faf619defa6846ae05c73eebd0bdf87e83045783 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:48:11 -0600 Subject: [PATCH 442/500] Convert advanced extractors to command blocks, back up data to them, fix various filter loading bugs --- .../extractor/AdvancedItemExtractorBlock.kt | 11 ++++-- .../blocks/extractor/CustomExtractorBlock.kt | 6 +++ .../filters/manager/FilterManager.kt | 13 ++++++- .../extractors/ChunkExtractorManager.kt | 16 +++++++- .../manager/extractors/ExtractorManager.kt | 17 ++++++++- .../extractors/ShipExtractorManager.kt | 2 +- .../nodes/cache/ItemTransportCache.kt | 2 +- .../transport/nodes/cache/NodeCacheFactory.kt | 37 +++++++++++-------- .../persistence/PDCSerializers.kt | 5 +++ 9 files changed, 82 insertions(+), 27 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index d9291b8287..9802e7ea30 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -4,7 +4,6 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.mushroomBlockData import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData @@ -13,14 +12,18 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.Material import org.bukkit.block.Block -import org.bukkit.block.BlockFace.DOWN -import org.bukkit.block.BlockFace.NORTH +import org.bukkit.block.BlockFace import org.bukkit.entity.Player object AdvancedItemExtractorBlock : CustomExtractorBlock( "ADVANCED_ITEM_EXTRACTOR", - mushroomBlockData(setOf(NORTH, DOWN, NORTH)), + blockData = Material.COMMAND_BLOCK.createBlockData { t -> + t as org.bukkit.block.data.type.CommandBlock + t.facing = BlockFace.UP + t.isConditional = false + }, BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ADVANCED_ITEM_EXTRACTOR) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index 2ab167c798..9fd4704496 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -5,6 +5,8 @@ import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -24,6 +26,10 @@ abstract class CustomExtractorBlock( ) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { val cooldown = PerPlayerCooldown(5L) + fun load(container: MetaDataContainer<*, *>): T { + return PDCSerializers.unpack(container) + } + override fun onRightClick(event: PlayerInteractEvent, block: Block) { val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt index 10b987b0c4..e50731df89 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.filters.manager import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.filter.CustomFilterBlock import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta @@ -44,11 +45,21 @@ abstract class FilterManager(open val manager: TransportManager<*>) { val saved = filters[key]?.let { data -> type.cast(data) } if (saved != null) return saved - val pdc = getPersistentDataContainer(key, manager.getWorld()) ?: return null + val globalVec3i = manager.getGlobalCoordinate(toVec3i(key)) + val pdc = getPersistentDataContainer(globalVec3i, manager.getWorld()) ?: return null val entityStored = pdc.get(NamespacedKeys.FILTER_DATA, FilterData)?.let { data -> type.cast(data) } if (entityStored != null) { filters[toBlockKey(manager.getLocalCoordinate(toVec3i(key)))] = entityStored } + if (entityStored == null) { + val block = manager.getWorld().getBlockData(globalVec3i.x, globalVec3i.y, globalVec3i.z) + val customBlock = CustomBlocks.getByBlockData(block) + if (customBlock !is CustomFilterBlock<*, *>) return null + + @Suppress("UNCHECKED_CAST") + return registerFilter(key, customBlock as CustomFilterBlock) + } + return entityStored } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt index 50e90c2aed..9afa0b5528 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ChunkExtractorManager.kt @@ -7,12 +7,15 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.data.Adv import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData.StandardExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData +import net.horizonsend.ion.server.features.transport.util.getPersistentDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.ListMetaDataContainerType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import org.bukkit.persistence.PersistentDataType @@ -36,7 +39,7 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag return null } - val data = getExtractorData(blockData, key) + val data = getExtractorData(blockData, key, manager.getWorld()) if (data == null) return null synchronized(mutex) { @@ -100,7 +103,16 @@ class ChunkExtractorManager(val manager: ChunkTransportManager) : ExtractorManag pdc.set(NamespacedKeys.STANDARD_EXTRACTORS, PersistentDataType.LONG_ARRAY, standard.keys.toLongArray()) val complex = extractors.values.filterIsInstance>() - val serialized = complex.map { it.asMetaDataContainer() } + + val serialized = complex.map { entry -> + val serialized = entry.asMetaDataContainer() + getPersistentDataContainer( + manager.getGlobalCoordinate(toVec3i(entry.pos)), + manager.getWorld() + )?.set(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer, serialized) + + serialized + } pdc.set(NamespacedKeys.COMPLEX_EXTRACTORS, ListMetaDataContainerType, serialized) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index d24891b550..1affb9d191 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -3,12 +3,16 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.extractor.CustomExtractorBlock import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.features.transport.util.getPersistentDataContainer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.Material +import org.bukkit.World import org.bukkit.block.data.BlockData abstract class ExtractorManager { @@ -36,11 +40,20 @@ abstract class ExtractorManager { val STANDARD_EXTRACTOR_TYPE = Material.CRAFTING_TABLE fun isExtractorData(data: BlockData): Boolean = data.material == STANDARD_EXTRACTOR_TYPE || CustomBlocks.getByBlockData(data) is CustomExtractorBlock<*> - fun getExtractorData(data: BlockData, pos: BlockKey): ExtractorData? { + fun getExtractorData(data: BlockData, pos: BlockKey, world: World): ExtractorData? { if (data.material == STANDARD_EXTRACTOR_TYPE) return ExtractorData.StandardExtractorData(pos) val customBlock = CustomBlocks.getByBlockData(data) - if (customBlock is CustomExtractorBlock<*>) return customBlock.createExtractorData(pos) + if (customBlock is CustomExtractorBlock<*>) { + val pdc = getPersistentDataContainer(pos, world) + val stored = pdc?.get(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer) + + if (stored != null) { + return customBlock.load(stored) + } + + return customBlock.createExtractorData(pos) + } return null } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt index 50c3d43c7c..719993b9d3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ShipExtractorManager.kt @@ -36,7 +36,7 @@ class ShipExtractorManager(val manager: ShipTransportManager) : ExtractorManager // Store extractors via local coordinates val key = toBlockKey(manager.getLocalCoordinate(Vec3i(x, y, z))) - val data = getExtractorData(blockData, key) + val data = getExtractorData(blockData, key, manager.getWorld()) if (data == null) return null extractors[key] = data diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index e2f56f1490..e48e706fe5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -44,7 +44,7 @@ class ItemTransportCache(override val holder: CacheHolder): override val extractorNodeClass: KClass = ItemNode.ItemExtractorNode::class override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) - .addSimpleNode(CustomBlocks.ADVANCED_ITEM_EXTRACTOR, ItemNode.ItemExtractorNode) + .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _ -> ItemNode.ItemExtractorNode } .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(STAINED_GLASS_PANE_TYPES) { _, material -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(Material.GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index 4974d33c10..ed5e5dfda0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import com.google.common.collect.Multimap import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.nodes.types.Node @@ -7,27 +8,29 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.horizonsend.ion.server.miscellaneous.utils.getTypeSafe +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.data.BlockData import kotlin.reflect.KClass -class NodeCacheFactory private constructor(private val materialHandlers: Map>) { +class NodeCacheFactory private constructor(private val materialHandlers: Multimap>) { fun cache(block: Block): Node? { val type = block.getTypeSafe() ?: return null - val materialFactory = materialHandlers[type] ?: return null + val forMaterial = materialHandlers[type] ?: return null val blockData = getBlockDataSafe(block.world, block.x, block.y, block.z) ?: return null - if (!materialFactory.blockDataClass.isInstance(blockData)) return null - return materialFactory.construct(blockData, toBlockKey(block.x, block.y, block.z)) + val filtered = forMaterial.filter { handler -> handler.blockDataClass.isInstance(blockData) } + + return filtered.firstNotNullOfOrNull { handler -> handler.construct(blockData, toBlockKey(block.x, block.y, block.z)) } } class Builder { - val materialHandlers = mutableMapOf>() + val materialHandlers = multimapOf>() inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node?): Builder { - this.materialHandlers[material] = MaterialHandler(T::class, constructor) + this.materialHandlers[material].add(MaterialHandler(T::class, constructor)) return this } @@ -41,44 +44,44 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map addDataHandler(materials: Iterable, noinline constructor: (T, BlockKey) -> Node): Builder { - for (material in materials) this.materialHandlers[material] = MaterialHandler(T::class, constructor) + for (material in materials) this.materialHandlers[material].add(MaterialHandler(T::class, constructor)) return this } inline fun addDataHandler(vararg materials: Material, noinline constructor: (T, BlockKey) -> Node?): Builder { - for (material in materials) this.materialHandlers[material] = MaterialHandler(T::class, constructor) + for (material in materials) this.materialHandlers[material].add(MaterialHandler(T::class, constructor)) return this } fun addSimpleNode(materials: Iterable, constructor: (BlockKey, Material) -> Node): Builder { - for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) } + for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) }) return this } fun addSimpleNode(vararg materials: Material, constructor: (BlockKey, Material) -> Node): Builder { - for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) } + for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) }) return this } fun addSimpleNode(material: Material, constructor: (BlockKey) -> Node): Builder { - this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, key -> constructor(key) } + this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, key -> constructor(key) }) return this } fun addSimpleNode(material: Material, node: Node): Builder { - this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } + this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, _ -> node }) return this } - fun addSimpleNode(customBlock: CustomBlock, node: Node): Builder { - return addDataHandler(customBlock.blockData.material) { data, lng -> + inline fun addSimpleNode(customBlock: CustomBlock, node: Node): Builder { + return addDataHandler(customBlock.blockData.material) { data, lng -> if (CustomBlocks.getByBlockData(data) != customBlock) return@addDataHandler null node } } fun addSimpleNode(materials: Iterable, node: Node): Builder { - for (material in materials) this.materialHandlers[material] = MaterialHandler(BlockData::class) { _, _ -> node } + for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, _ -> node }) return this } @@ -93,7 +96,9 @@ class NodeCacheFactory private constructor(private val materialHandlers: Map exception.printStackTrace() } + .getOrNull() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt index 4fd3d2e887..ff2b8849fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/PDCSerializers.kt @@ -49,4 +49,9 @@ object PDCSerializers { val serializer = (typedSerialized[data::class] as? RegisteredSerializer) ?: throw NoSuchElementException("No serialier found for ${data::class.simpleName}") return MetaDataContainer(serializer, data) } + + fun unpack(metaDataContainer: MetaDataContainer<*, *>): T { + @Suppress("UNCHECKED_CAST") + return metaDataContainer.data as T + } } From 3cbf5113940d9c4bac5711554dd4dc78def53626 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:50:37 -0600 Subject: [PATCH 443/500] save chunk filter manager --- .../net/horizonsend/ion/server/features/world/chunk/IonChunk.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt index 7e57544528..6a95cb4d24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/chunk/IonChunk.kt @@ -74,6 +74,7 @@ class IonChunk(val inner: Chunk) { fun save() { multiblockManager.save() transportNetwork.extractorManager.save() + transportNetwork.filterManager.save() } /** From 25710ac194b9d54643d3215b95d78ee4935f8dba Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:52:00 -0600 Subject: [PATCH 444/500] make command blocks flyable --- .../horizonsend/ion/server/features/starship/FlyableBlocks.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt index c92640597e..9ebf6f4222 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt @@ -44,6 +44,7 @@ import org.bukkit.Material.CHAIN import org.bukkit.Material.CHEST import org.bukkit.Material.CHIPPED_ANVIL import org.bukkit.Material.COAL_BLOCK +import org.bukkit.Material.COMMAND_BLOCK import org.bukkit.Material.COMPARATOR import org.bukkit.Material.COMPOSTER import org.bukkit.Material.COPPER_BLOCK @@ -207,6 +208,7 @@ val FLYABLE_BLOCKS: EnumSet = mutableSetOf( EMERALD_BLOCK, COAL_BLOCK, BROWN_MUSHROOM_BLOCK, // custom ores + COMMAND_BLOCK, // custom blocks // used for landing gears PISTON, From f085e17cc3e906dc71a181e8b10c736fe73a84a7 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:06:25 -0600 Subject: [PATCH 445/500] Move node cache factory to cache type --- .../nodes/cache/FluidTransportCache.kt | 22 ----- .../nodes/cache/ItemTransportCache.kt | 30 ------ .../transport/nodes/cache/NodeCacheFactory.kt | 41 +++++---- .../nodes/cache/PowerTransportCache.kt | 22 ----- .../transport/nodes/cache/SolarPanelCache.kt | 7 -- .../transport/nodes/cache/TransportCache.kt | 4 +- .../features/transport/util/CacheType.kt | 92 +++++++++++++++++++ 7 files changed, 115 insertions(+), 103 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index 8b9aa56b5e..d827781093 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -13,36 +13,14 @@ import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion -import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES -import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Material -import org.bukkit.Material.CRAFTING_TABLE -import org.bukkit.Material.WAXED_CHISELED_COPPER -import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER -import org.bukkit.Material.WAXED_OXIDIZED_COPPER -import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.block.BlockFace -import org.bukkit.craftbukkit.block.impl.CraftLightningRod import kotlin.math.roundToInt import kotlin.reflect.KClass class FluidTransportCache(holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.FLUID override val extractorNodeClass: KClass = FluidNode.FluidExtractorNode::class - override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() - .addDataHandler(Material.LIGHTNING_ROD) { data, _ -> FluidNode.LightningRodNode(data.facing.axis) } - .addSimpleNode(WAXED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_CHISELED_COPPER) } - .addSimpleNode(WAXED_EXPOSED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_EXPOSED_CHISELED_COPPER) } - .addSimpleNode(WAXED_WEATHERED_CHISELED_COPPER) { FluidNode.FluidJunctionNode(WAXED_WEATHERED_CHISELED_COPPER) } - .addSimpleNode(WAXED_OXIDIZED_COPPER) { FluidNode.FluidJunctionNode(WAXED_OXIDIZED_COPPER) } - .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { _, _ -> FluidNode.FluidJunctionNode(CRAFTING_TABLE) } // All unwaxed chiseled are a single channel - .addSimpleNode(CRAFTING_TABLE, FluidNode.FluidExtractorNode) - .addSimpleNode(Material.FLETCHING_TABLE, FluidNode.FluidInputNode) - .addSimpleNode(Material.REDSTONE_BLOCK, FluidNode.FluidMergeNode) - .addSimpleNode(Material.IRON_BLOCK, FluidNode.FluidMergeNode) - .addSimpleNode(Material.LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) - .build() override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { NewTransport.runTask { val world = holder.getWorld() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index e48e706fe5..bdb0d75eab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -5,7 +5,6 @@ import net.horizonsend.ion.common.extensions.serverError import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock -import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.features.transport.items.transaction.Change @@ -14,14 +13,11 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.data.Ext import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode -import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getBlockEntity import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES -import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -29,12 +25,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.minecraft.world.Container import net.minecraft.world.level.block.entity.BlockEntity -import org.bukkit.Material -import org.bukkit.Material.CRAFTING_TABLE import org.bukkit.block.BlockFace -import org.bukkit.block.data.type.CommandBlock -import org.bukkit.block.data.type.Hopper -import org.bukkit.craftbukkit.block.impl.CraftGrindstone import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass @@ -42,27 +33,6 @@ import kotlin.reflect.KClass class ItemTransportCache(override val holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.ITEMS override val extractorNodeClass: KClass = ItemNode.ItemExtractorNode::class - override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() - .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) - .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _ -> ItemNode.ItemExtractorNode } - .addSimpleNode(STAINED_GLASS_TYPES) { _, material -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } - .addSimpleNode(STAINED_GLASS_PANE_TYPES) { _, material -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } - .addSimpleNode(Material.GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) - .addSimpleNode(Material.GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) - .addSimpleNode(Material.TINTED_GLASS, ItemNode.WildcardSolidGlassNode) - .addDataHandler(Material.GRINDSTONE) { data, key -> ItemNode.ItemMergeNode } - .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key -> ItemNode.AdvancedFilterNode(key, this) } - .addDataHandler(Material.HOPPER) { data, key -> ItemNode.HopperFilterNode(key, data.facing, this) } - .addSimpleNode( - Material.CHEST, - Material.TRAPPED_CHEST, - Material.BARREL, - Material.FURNACE, - Material.DISPENSER, - Material.DROPPER, - Material.DECORATED_POT - ) { key, _ -> ItemNode.InventoryNode(key) } - .build() override fun tickExtractor( location: BlockKey, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index ed5e5dfda0..f30dbc0f84 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import com.google.common.collect.Multimap import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey @@ -15,7 +16,7 @@ import org.bukkit.block.data.BlockData import kotlin.reflect.KClass class NodeCacheFactory private constructor(private val materialHandlers: Multimap>) { - fun cache(block: Block): Node? { + fun cache(block: Block, holder: CacheHolder<*>): Node? { val type = block.getTypeSafe() ?: return null val forMaterial = materialHandlers[type] ?: return null @@ -23,65 +24,65 @@ class NodeCacheFactory private constructor(private val materialHandlers: Multima val filtered = forMaterial.filter { handler -> handler.blockDataClass.isInstance(blockData) } - return filtered.firstNotNullOfOrNull { handler -> handler.construct(blockData, toBlockKey(block.x, block.y, block.z)) } + return filtered.firstNotNullOfOrNull { handler -> handler.construct(blockData, toBlockKey(block.x, block.y, block.z), holder) } } class Builder { val materialHandlers = multimapOf>() - inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey) -> Node?): Builder { + inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey, CacheHolder<*>) -> Node?): Builder { this.materialHandlers[material].add(MaterialHandler(T::class, constructor)) return this } - inline fun addDataHandler(customBlock: CustomBlock, noinline constructor: (T, BlockKey) -> Node?): Builder { + inline fun addDataHandler(customBlock: CustomBlock, noinline constructor: (T, BlockKey, CacheHolder<*>) -> Node?): Builder { require(customBlock.blockData is T) - return addDataHandler(customBlock.blockData.material) { data, lng -> + return addDataHandler(customBlock.blockData.material) { data, lng, holder -> if (CustomBlocks.getByBlockData(data) != customBlock) return@addDataHandler null - constructor.invoke(data, lng) + constructor.invoke(data, lng, holder) } } - inline fun addDataHandler(materials: Iterable, noinline constructor: (T, BlockKey) -> Node): Builder { + inline fun addDataHandler(materials: Iterable, noinline constructor: (T, BlockKey, CacheHolder<*>) -> Node): Builder { for (material in materials) this.materialHandlers[material].add(MaterialHandler(T::class, constructor)) return this } - inline fun addDataHandler(vararg materials: Material, noinline constructor: (T, BlockKey) -> Node?): Builder { + inline fun addDataHandler(vararg materials: Material, noinline constructor: (T, BlockKey, CacheHolder<*>) -> Node?): Builder { for (material in materials) this.materialHandlers[material].add(MaterialHandler(T::class, constructor)) return this } - fun addSimpleNode(materials: Iterable, constructor: (BlockKey, Material) -> Node): Builder { - for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) }) + fun addSimpleNode(materials: Iterable, constructor: (BlockKey, Material, CacheHolder<*>) -> Node): Builder { + for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { data, key, holder -> constructor(key, data.material, holder) }) return this } - fun addSimpleNode(vararg materials: Material, constructor: (BlockKey, Material) -> Node): Builder { - for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { data, key -> constructor(key, data.material) }) + fun addSimpleNode(vararg materials: Material, constructor: (BlockKey, Material, CacheHolder<*>) -> Node): Builder { + for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { data, key, holder -> constructor(key, data.material, holder) }) return this } - fun addSimpleNode(material: Material, constructor: (BlockKey) -> Node): Builder { - this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, key -> constructor(key) }) + fun addSimpleNode(material: Material, constructor: (BlockKey, CacheHolder<*>) -> Node): Builder { + this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, key, holder -> constructor(key, holder) }) return this } fun addSimpleNode(material: Material, node: Node): Builder { - this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, _ -> node }) + this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, _, _ -> node }) return this } inline fun addSimpleNode(customBlock: CustomBlock, node: Node): Builder { - return addDataHandler(customBlock.blockData.material) { data, lng -> + return addDataHandler(customBlock.blockData.material) { data, lng, _ -> if (CustomBlocks.getByBlockData(data) != customBlock) return@addDataHandler null node } } fun addSimpleNode(materials: Iterable, node: Node): Builder { - for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, _ -> node }) + for (material in materials) this.materialHandlers[material].add(MaterialHandler(BlockData::class) { _, _, _ -> node }) return this } @@ -92,11 +93,11 @@ class NodeCacheFactory private constructor(private val materialHandlers: Multima } } - class MaterialHandler(val blockDataClass: KClass, val constructor: (T, BlockKey) -> Node?) { + class MaterialHandler(val blockDataClass: KClass, val constructor: (T, BlockKey, CacheHolder<*>) -> Node?) { @Synchronized - fun construct(blockData: BlockData, key: BlockKey): Node? { + fun construct(blockData: BlockData, key: BlockKey, holder: CacheHolder<*>): Node? { @Suppress("UNCHECKED_CAST") - return runCatching { constructor.invoke(blockData as T, key) } + return runCatching { constructor.invoke(blockData as T, key, holder) } .onFailure { exception -> exception.printStackTrace() } .getOrNull() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 91da918079..8073097569 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -12,19 +12,8 @@ import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.miscellaneous.utils.axis import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Material.CRAFTING_TABLE -import org.bukkit.Material.END_ROD -import org.bukkit.Material.IRON_BLOCK -import org.bukkit.Material.LAPIS_BLOCK -import org.bukkit.Material.NOTE_BLOCK -import org.bukkit.Material.OBSERVER -import org.bukkit.Material.REDSTONE_BLOCK -import org.bukkit.Material.SPONGE import org.bukkit.block.BlockFace -import org.bukkit.block.data.type.Observer -import org.bukkit.craftbukkit.block.impl.CraftEndRod import kotlin.math.roundToInt import kotlin.reflect.KClass @@ -32,17 +21,6 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override val type: CacheType = CacheType.POWER override val extractorNodeClass: KClass = PowerNode.PowerExtractorNode::class - override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() - .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) - .addSimpleNode(SPONGE, PowerNode.SpongeNode) - .addDataHandler(END_ROD) { data, _ -> PowerNode.EndRodNode(data.facing.axis) } - .addSimpleNode(REDSTONE_BLOCK, PowerNode.RedstoneMergeNode) - .addSimpleNode(IRON_BLOCK, PowerNode.IronMergeNode) - .addSimpleNode(LAPIS_BLOCK, PowerNode.InvertedMergeNode) - .addDataHandler(OBSERVER) { data, loc -> PowerFlowMeter(this, data.facing, holder.getWorld(), loc) } - .addSimpleNode(NOTE_BLOCK, PowerInputNode) - .build() - override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { val solarCache = holder.transportManager.solarPanelManager.cache if (solarCache.isSolarPanel(location)) tickSolarPanel(location, delta, solarCache) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt index 066f29cee8..0eb565d8b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt @@ -10,7 +10,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe -import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.data.type.DaylightDetector @@ -18,12 +17,6 @@ import kotlin.math.roundToInt import kotlin.reflect.KClass class SolarPanelCache(holder: CacheHolder) : TransportCache(holder) { - override val nodeFactory: NodeCacheFactory = NodeCacheFactory.builder() - .addSimpleNode(Material.CRAFTING_TABLE, SolarPanelComponent.CraftingTable) - .addSimpleNode(Material.DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) - .addSimpleNode(Material.DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) - .build() - override val type: CacheType = CacheType.SOLAR_PANELS override val extractorNodeClass: KClass = PowerNode.PowerExtractorNode::class diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 45ee471310..355b5b6f11 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -46,7 +46,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { private val pathCache = TreeBasedTable.create>() abstract val type: CacheType - abstract val nodeFactory: NodeCacheFactory + val nodeFactory: NodeCacheFactory get() = type.nodeCacheFactory abstract fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) @@ -77,7 +77,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { // On race conditions nodeCache[location]?.let { return@synchronized (it as? CacheState.Present)?.node } - val type = nodeFactory.cache(block) + val type = nodeFactory.cache(block, this.holder) val state = if (type == null) CacheState.Empty else CacheState.Present(type) nodeCache[location] = state diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index 52a6626325..df9546c675 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -1,18 +1,66 @@ package net.horizonsend.ion.server.features.transport.util +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.NodeCacheFactory import net.horizonsend.ion.server.features.transport.nodes.cache.PowerTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache +import net.horizonsend.ion.server.features.transport.nodes.cache.SolarPanelCache.SolarPanelComponent import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode +import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode +import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidGlassNode +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter +import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType.entries import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys +import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES +import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES +import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES +import net.horizonsend.ion.server.miscellaneous.utils.axis +import org.bukkit.Material +import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.Material.END_ROD +import org.bukkit.Material.FLETCHING_TABLE +import org.bukkit.Material.GLASS +import org.bukkit.Material.GLASS_PANE +import org.bukkit.Material.GRINDSTONE +import org.bukkit.Material.IRON_BLOCK +import org.bukkit.Material.LAPIS_BLOCK +import org.bukkit.Material.NOTE_BLOCK +import org.bukkit.Material.OBSERVER +import org.bukkit.Material.REDSTONE_BLOCK +import org.bukkit.Material.SPONGE +import org.bukkit.Material.TINTED_GLASS +import org.bukkit.Material.WAXED_CHISELED_COPPER +import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER +import org.bukkit.Material.WAXED_OXIDIZED_COPPER +import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.NamespacedKey +import org.bukkit.block.data.type.CommandBlock +import org.bukkit.block.data.type.Hopper +import org.bukkit.block.data.type.Observer +import org.bukkit.craftbukkit.block.impl.CraftEndRod +import org.bukkit.craftbukkit.block.impl.CraftGrindstone +import org.bukkit.craftbukkit.block.impl.CraftLightningRod enum class CacheType(val namespacedKey: NamespacedKey) { POWER(NamespacedKeys.POWER_TRANSPORT) { + override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(CRAFTING_TABLE, PowerNode.PowerExtractorNode) + .addSimpleNode(SPONGE, PowerNode.SpongeNode) + .addDataHandler(END_ROD) { data, _, _ -> PowerNode.EndRodNode(data.facing.axis) } + .addSimpleNode(REDSTONE_BLOCK, PowerNode.RedstoneMergeNode) + .addSimpleNode(IRON_BLOCK, PowerNode.IronMergeNode) + .addSimpleNode(LAPIS_BLOCK, PowerNode.InvertedMergeNode) + .addDataHandler(OBSERVER) { data, loc, holder -> PowerFlowMeter(holder.cache as PowerTransportCache, data.facing, holder.getWorld(), loc) } + .addSimpleNode(NOTE_BLOCK, PowerInputNode) + .build() + override fun get(chunk: IonChunk): PowerTransportCache { return chunk.transportNetwork.powerNodeManager.cache } @@ -22,6 +70,12 @@ enum class CacheType(val namespacedKey: NamespacedKey) { } }, SOLAR_PANELS(NamespacedKeys.POWER_TRANSPORT) { + override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(Material.CRAFTING_TABLE, SolarPanelComponent.CraftingTable) + .addSimpleNode(Material.DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) + .addSimpleNode(Material.DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) + .build() + override fun get(chunk: IonChunk): SolarPanelCache { return chunk.transportNetwork.solarPanelManager.cache } @@ -31,6 +85,20 @@ enum class CacheType(val namespacedKey: NamespacedKey) { } }, FLUID(NamespacedKeys.FLUID_TRANSPORT) { + override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addDataHandler(Material.LIGHTNING_ROD) { data, _, _ -> FluidNode.LightningRodNode(data.facing.axis) } + .addSimpleNode(WAXED_CHISELED_COPPER) { _, _ -> FluidNode.FluidJunctionNode(WAXED_CHISELED_COPPER) } + .addSimpleNode(WAXED_EXPOSED_CHISELED_COPPER) { _, _ -> FluidNode.FluidJunctionNode(WAXED_EXPOSED_CHISELED_COPPER) } + .addSimpleNode(WAXED_WEATHERED_CHISELED_COPPER) { _, _ -> FluidNode.FluidJunctionNode(WAXED_WEATHERED_CHISELED_COPPER) } + .addSimpleNode(WAXED_OXIDIZED_COPPER) { _, _ -> FluidNode.FluidJunctionNode(WAXED_OXIDIZED_COPPER) } + .addSimpleNode(UNWAXED_CHISELED_COPPER_TYPES) { _, _, _ -> FluidNode.FluidJunctionNode(CRAFTING_TABLE) } // All unwaxed chiseled are a single channel + .addSimpleNode(CRAFTING_TABLE, FluidNode.FluidExtractorNode) + .addSimpleNode(FLETCHING_TABLE, FluidNode.FluidInputNode) + .addSimpleNode(REDSTONE_BLOCK, FluidNode.FluidMergeNode) + .addSimpleNode(IRON_BLOCK, FluidNode.FluidMergeNode) + .addSimpleNode(LAPIS_BLOCK, FluidNode.FluidInvertedMergeNode) + .build() + override fun get(chunk: IonChunk): FluidTransportCache { TODO("Fluid is disabled") // return chunk.transportNetwork.fluidNodeManager.cache @@ -42,6 +110,28 @@ enum class CacheType(val namespacedKey: NamespacedKey) { } }, ITEMS(NamespacedKeys.ITEM_TRANSPORT) { + override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() + .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) + .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _, _ -> ItemNode.ItemExtractorNode } + .addSimpleNode(STAINED_GLASS_TYPES) { _, material, _ -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } + .addSimpleNode(STAINED_GLASS_PANE_TYPES) { _, material, _ -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } + .addSimpleNode(GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) + .addSimpleNode(GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) + .addSimpleNode(TINTED_GLASS, ItemNode.WildcardSolidGlassNode) + .addDataHandler(GRINDSTONE) { data, key, _ -> ItemNode.ItemMergeNode } + .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache) } + .addDataHandler(Material.HOPPER) { data, key, holder -> ItemNode.HopperFilterNode(key, data.facing, holder.cache as ItemTransportCache) } + .addSimpleNode( + Material.CHEST, + Material.TRAPPED_CHEST, + Material.BARREL, + Material.FURNACE, + Material.DISPENSER, + Material.DROPPER, + Material.DECORATED_POT + ) { key, _, _ -> ItemNode.InventoryNode(key) } + .build() + override fun get(chunk: IonChunk): ItemTransportCache { return chunk.transportNetwork.itemPipeManager.cache } @@ -53,6 +143,8 @@ enum class CacheType(val namespacedKey: NamespacedKey) { ; + abstract val nodeCacheFactory: NodeCacheFactory + abstract fun get(chunk: IonChunk): TransportCache abstract fun get(ship: ActiveStarship): TransportCache From 853f43a11c4448dbe20ad1ebaec884b98bae0f77 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 29 Jan 2025 15:58:54 -0600 Subject: [PATCH 446/500] group by inventory --- .../nodes/cache/ItemTransportCache.kt | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index bdb0d75eab..8bdd84e636 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -23,10 +23,12 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience +import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import net.minecraft.world.Container import net.minecraft.world.level.block.entity.BlockEntity import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.inventory.CraftInventory +import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass @@ -54,16 +56,19 @@ class ItemTransportCache(override val holder: CacheHolder): return } - val items = sources.flatMap { inv -> inv }.filterNotNull() - if (items.isEmpty()) return + val byInventory = sources.associateWith { stacks -> stacks.filterNotNull() } + if (byInventory.isEmpty()) return val byCount = mutableMapOf() - - for (item in items) { - val asOne = item.asOne() - if (byCount.containsKey(asOne)) continue - val count = items.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } - byCount[asOne] = count + val itemReferences = multimapOf>() + + for ((inventory, items) in byInventory) { + for (item in items) { + val asOne = item.asOne() + if (byCount.containsKey(asOne)) continue + val count = items.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } + byCount[asOne] = count + } } debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") From 5432d02d62cb51d09f16becf1f2b1faabce125e3 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 12:20:39 -0600 Subject: [PATCH 447/500] shorten E/sec to delta e --- .../client/display/modular/display/FlowMeterDisplayModule.kt | 5 +---- .../ion/server/features/transport/nodes/types/PowerNode.kt | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt index adb206030e..4836d90715 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/client/display/modular/display/FlowMeterDisplayModule.kt @@ -1,11 +1,9 @@ package net.horizonsend.ion.server.features.client.display.modular.display -import net.horizonsend.ion.common.utils.text.colors.HEColorScheme.Companion.HE_MEDIUM_GRAY import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.newline import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.GREEN import net.kyori.adventure.text.format.NamedTextColor.YELLOW @@ -26,7 +24,6 @@ class FlowMeterDisplayModule( } companion object { - val firstLine = text("E: ", YELLOW) - val secondLine = ofChildren(newline(), text("E ", YELLOW), text("/ ", HE_MEDIUM_GRAY), text("Sec", GREEN)) + val firstLine = ofChildren(text("Δ", GREEN), text("E: ", YELLOW)) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index ebf6b06b53..39e71e6456 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -117,7 +117,6 @@ sealed interface PowerNode : Node { return ofChildren( FlowMeterDisplayModule.firstLine, Component.text(format.format(avg), NamedTextColor.GREEN), - FlowMeterDisplayModule.secondLine ) } From f6258b2f61105db589cdd94e82091de35cf7489c Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:20:50 -0600 Subject: [PATCH 448/500] Back item transfers with removals from origin --- .../transaction/BackedItemTransaction.kt | 52 ++++++ .../transport/items/transaction/Change.kt | 81 --------- .../items/transaction/ItemReference.kt | 11 ++ .../items/transaction/ItemTransaction.kt | 61 ++----- .../nodes/cache/ItemTransportCache.kt | 154 +++++++++++------- 5 files changed, 166 insertions(+), 193 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt delete mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt new file mode 100644 index 0000000000..f0b0d59bce --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt @@ -0,0 +1,52 @@ +package net.horizonsend.ion.server.features.transport.items.transaction + +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack + +class BackedItemTransaction(val source: ItemReference, val item: ItemStack, val amount: Int, val destination: Inventory) { + fun check(): Boolean { + return true + } + + fun execute() { + val cloned = source.inventory.getItem(source.index)?.clone() ?: return + val notRemoved = tryRemove() + + println("Not removed: $notRemoved") + val limit = amount - notRemoved + + println("Limit: $limit") + + if (limit <= 0) return + + println("Adding to destination") + val notAdded = addToDestination(limit) + println("Not added: $notAdded") + if (notAdded <= 0) return + + source.inventory.setItem(source.index, cloned.asQuantity(notAdded)) + } + + // Returns amount that could not be removed + fun tryRemove(): Int { + val stack = source.inventory.getItem(source.index) + if (stack == null) return amount + + val removeAmount = minOf(amount, stack.amount) + + return if (amount == removeAmount) { + source.inventory.setItem(source.index, null) + + 0 + } else { + source.inventory.getItem(source.index)?.amount -= removeAmount + + amount - removeAmount + } + } + + // Returns amount that did not fit + fun addToDestination(limit: Int): Int { + return destination.addItem(item.asQuantity(limit)).values.firstOrNull()?.amount ?: 0 + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt deleted file mode 100644 index 736bc12015..0000000000 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/Change.kt +++ /dev/null @@ -1,81 +0,0 @@ -package net.horizonsend.ion.server.features.transport.items.transaction - -import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils -import org.bukkit.inventory.Inventory -import org.bukkit.inventory.ItemStack -import kotlin.math.abs - -interface Change { - fun check(inventory: Inventory): Boolean - - fun execute(inventory: Inventory): Boolean - - class ItemRemoval(val item: ItemStack, val amount: Int) : Change { - override fun check(inventory: Inventory): Boolean { - return true //TODO - } - - override fun execute(inventory: Inventory): Boolean { - val byCount = mutableMapOf() - val contents = inventory.contents.filterNotNull() - - for (item in contents) { - val asOne = item.asOne() - if (byCount.containsKey(asOne)) continue - val count = contents.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } - byCount[asOne] = count - } - - val toRemove = abs(amount) - - if (byCount.getOrDefault(item, 0) < toRemove) return false - - var remaining = toRemove - - var iterations = 0 - // Upper bound of inventory as double chest size - while (remaining > 0 && iterations < 54) { - iterations++ - val invItem = contents.first { stack -> stack.isSimilar(item) } - val amount = invItem.amount - - val toRemove = minOf(amount, remaining) - - remaining -= toRemove - - if (toRemove == invItem.maxStackSize) { - inventory.remove(invItem) - } - - invItem.amount -= toRemove - } - - return true - } - } - - class ItemAddition(val item: ItemStack, val amount: Int) : Change { - override fun check(inventory: Inventory): Boolean { - return LegacyItemUtils.canFit(inventory, item, amount) //TODO - } - - override fun execute(inventory: Inventory): Boolean { - val stacks = mutableListOf() - - var remaining = amount - var iterations = 0 - while (remaining > 0 && iterations < 54) { - iterations++ - - val maxStackSize = item.maxStackSize - val newAmount = minOf(maxStackSize, remaining) - remaining -= newAmount - stacks.add(item.asQuantity(newAmount)) - } - - stacks.forEach(inventory::addItem) - - return true - } - } -} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt new file mode 100644 index 0000000000..5fcd9c45d8 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt @@ -0,0 +1,11 @@ +package net.horizonsend.ion.server.features.transport.items.transaction + +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack + +data class ItemReference( + val inventory: Inventory, + val index: Int +) { + fun get(): ItemStack? = inventory.getItem(index) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt index 83239699d2..add19aa5b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemTransaction.kt @@ -1,63 +1,22 @@ package net.horizonsend.ion.server.features.transport.items.transaction -import net.horizonsend.ion.server.features.transport.items.transaction.Change.ItemAddition -import net.horizonsend.ion.server.features.transport.items.transaction.Change.ItemRemoval -import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder -import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack -class ItemTransaction(val originCacheHolder: CacheHolder) { - val removals = multimapOf() - val additions = multimapOf() +class ItemTransaction() { + val transactions = mutableListOf() - fun addRemoval(sourcePos: BlockKey, diff: ItemRemoval) { - removals[sourcePos].add(diff) - } - - fun addAddition(sourcePos: BlockKey, diff: ItemAddition) { - additions[sourcePos].add(diff) - } - - data class CommitContext(val key: BlockKey, val inventory: Inventory, val change: Change) { - fun check() = change.check(inventory) - fun commit() = change.execute(inventory) + fun addTransfer(sourceReference: ItemReference, destinationInventory: Inventory, transferredItem: ItemStack, transferredAmount: Int) { + transactions += BackedItemTransaction(sourceReference, transferredItem, transferredAmount, destinationInventory) } fun commit() { - val inventories = mutableMapOf() - - val removalContexts = mutableListOf() - val additionContexts = mutableListOf() - - val getInventory = fun(key: BlockKey): Inventory? { - return inventories.getOrPut(key) { originCacheHolder.cache.getInventory(key) } - } - - removals.entries().mapNotNullTo(removalContexts) { entry -> - val inventory = getInventory(entry.key) ?: return@mapNotNullTo null - CommitContext(entry.key, inventory, entry.value) - } - - additions.entries().mapNotNullTo(additionContexts) { entry -> - val inventory = getInventory(entry.key) ?: return@mapNotNullTo null - CommitContext(entry.key, inventory, entry.value) - } - - if (!checkAll(removalContexts)) return - if (!checkAll(additionContexts)) return - - for (removal in removalContexts) { - removal.commit() - } - - for (addition in additionContexts) { - addition.commit() - } + transactions + .filter { transaction -> transaction.check() } + .forEach { t -> t.execute() } } - fun checkAll(contexts: Collection): Boolean { - return contexts.all { context -> context.check() } + fun checkAll(): Boolean { + return transactions.all { transaction -> transaction.check() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 8bdd84e636..18d0adb0eb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -1,13 +1,12 @@ package net.horizonsend.ion.server.features.transport.nodes.cache +import com.google.common.collect.Multimap import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.serverError import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.NewTransport -import net.horizonsend.ion.server.features.transport.items.SortingOrder -import net.horizonsend.ion.server.features.transport.items.transaction.Change +import net.horizonsend.ion.server.features.transport.items.transaction.ItemReference import net.horizonsend.ion.server.features.transport.items.transaction.ItemTransaction import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData @@ -20,12 +19,10 @@ import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import net.minecraft.world.Container -import net.minecraft.world.level.block.entity.BlockEntity import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.inventory.Inventory @@ -49,100 +46,135 @@ class ItemTransportCache(override val holder: CacheHolder): } fun handleExtractorTick(location: BlockKey, delta: Double, meta: ItemExtractorMetaData?) { - val distributionOrder = meta?.sortingOrder ?: SortingOrder.NEAREST_FIRST - val sources = getSources(location) if (sources.isEmpty()) { return } - val byInventory = sources.associateWith { stacks -> stacks.filterNotNull() } + val byInventory: Map>> = sources.associateWith { stacks -> stacks.withIndex().filter { (_, value) -> value != null } } if (byInventory.isEmpty()) return val byCount = mutableMapOf() - val itemReferences = multimapOf>() + val itemReferences = multimapOf() for ((inventory, items) in byInventory) { - for (item in items) { + for ((index, item) in items) { val asOne = item.asOne() + + itemReferences[asOne].add(ItemReference(inventory, index)) + if (byCount.containsKey(asOne)) continue - val count = items.sumOf { stack -> if (stack.isSimilar(item)) stack.amount else 0 } + val count = items.sumOf { stack -> if (stack.value.isSimilar(item)) stack.value.amount else 0 } byCount[asOne] = count } } debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") + debugAudience.information("references: [${itemReferences.entries().joinToString { "${it.key} ${it.value}" }}, ${toVec3i(location)}") val originNode = getOrCache(location) ?: return - for ((item, count) in byCount) { - debugAudience.information("Checking ${item.type} [$count]") + val destinationInvCache = mutableMapOf() + + for ((item, count) in byCount) transferItemType( + location, + originNode, + meta, + item, + count, + destinationInvCache, + itemReferences + ) + } - val destinations: List = getNetworkDestinations(location, originNode) { node -> - val inventory = getInventory(node.position) - inventory != null && LegacyItemUtils.canFit(inventory, item, 1) - }.toList() + fun transferItemType( + originKey: BlockKey, + originNode: Node, + meta: ItemExtractorMetaData?, + singletonItem: ItemStack, + count: Int, + destinationInvCache: MutableMap, + itemReferences: Multimap, + ) { + val availableItemReferences = itemReferences[singletonItem] + debugAudience.information("Checking ${singletonItem.type} [$count]") - if (destinations.isEmpty()) { - debugAudience.information("No destinations found") - continue + val destinations: List = getNetworkDestinations(originKey, originNode) { node -> + val inventory = destinationInvCache.getOrPut(node.position) { + getInventory(node.position) ?: return@getNetworkDestinations false } - val numDestinations = destinations.size - - val paths: Array = measureOrFallback(TransportDebugCommand.pathfindTimes) { Array(numDestinations) { - findPath( - origin = Node.NodePositionData( - ItemNode.ItemExtractorNode, - holder.getWorld(), - location, - BlockFace.SELF - ), - destination = destinations[it], - ignoreCache = true // TODO wait for a caching implementation that will allow compound keys for item types - ) { node, blockFace -> - if (node !is ItemNode.FilterNode) return@findPath true - debugAudience.serverError("checking filter") - node.matches(item) - } - } } - -// var destinationMap = mutableMapOf() - - val validDestinations = destinations.filterIndexed { index, destination -> - val path = paths[index] -// path?.let { destinationMap[destination] = index } - path != null - } + LegacyItemUtils.canFit(inventory, singletonItem, 1) + }.toList() - if (validDestinations.isEmpty()) { - return - } + if (destinations.isEmpty()) return debugAudience.information("No destinations found") + + val numDestinations = destinations.size - meta?.markItemPathfind(item) + val paths: Array = Array(numDestinations) { + findPath( + origin = Node.NodePositionData( + ItemNode.ItemExtractorNode, + holder.getWorld(), + originKey, + BlockFace.SELF + ), + destination = destinations[it], + ignoreCache = true // TODO wait for a caching implementation that will allow compound keys for item types + ) { node, blockFace -> + if (node !is ItemNode.FilterNode) return@findPath true - val destination = if (meta != null) { - distributionOrder.getDestination(meta, validDestinations) - } else { - val extractorPosition = toVec3i(location) - destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } + node.matches(singletonItem) } + } + + val validDestinations = destinations.filterIndexedTo(mutableListOf()) { index, destination -> + val path = paths[index] + path != null + } + if (validDestinations.isEmpty()) return + +// meta?.markItemPathfind(item) TODO path caching for items + + val transaction = ItemTransaction() + + for (reference in availableItemReferences) { + var destination = getDestination(meta, originKey, validDestinations) debugAudience.information("Selected destination ${toVec3i(destination)}") - val transact = ItemTransaction(holder) + val destinationInventory = destinationInvCache[destination]!! + val room = LegacyItemUtils.getSpaceFor(destinationInventory, singletonItem) - for (source in sources) { - val key = toBlockKey((source.inventory as BlockEntity).blockPos.toVec3i()) - transact.addRemoval(key, Change.ItemRemoval(item, count)) + if (room == 0) { + validDestinations.remove(destination) + destination = getDestination(meta, originKey, validDestinations) + continue } - transact.addAddition(destination, Change.ItemAddition(item, count)) + val amount = minOf(reference.get()?.amount ?: 0, room) + if (amount == 0) continue - transact.commit() + transaction.addTransfer( + reference, + destinationInventory, + singletonItem, + amount + ) debugAudience.highlightBlock(toVec3i(destination), 40L) } + + transaction.commit() + } + + fun getDestination(meta: ItemExtractorMetaData?, extractorKey: BlockKey, destinations: List): BlockKey { + if (meta != null) { + return meta.sortingOrder.getDestination(meta, destinations) + } + + val extractorPosition = toVec3i(extractorKey) + return destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } } fun getInventory(localKey: BlockKey): CraftInventory? { From 9d83015cb6823bfc7890bf02a30c35de79814737 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 14:22:49 -0600 Subject: [PATCH 449/500] remove printlns, extended logging --- .../items/transaction/BackedItemTransaction.kt | 5 ----- .../transport/nodes/cache/ItemTransportCache.kt | 15 ++++++--------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt index f0b0d59bce..60fdd27a96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/BackedItemTransaction.kt @@ -12,16 +12,11 @@ class BackedItemTransaction(val source: ItemReference, val item: ItemStack, val val cloned = source.inventory.getItem(source.index)?.clone() ?: return val notRemoved = tryRemove() - println("Not removed: $notRemoved") val limit = amount - notRemoved - println("Limit: $limit") - if (limit <= 0) return - println("Adding to destination") val notAdded = addToDestination(limit) - println("Not added: $notAdded") if (notAdded <= 0) return source.inventory.setItem(source.index, cloned.asQuantity(notAdded)) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 18d0adb0eb..bc5925acde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -1,10 +1,8 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import com.google.common.collect.Multimap -import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.items.transaction.ItemReference import net.horizonsend.ion.server.features.transport.items.transaction.ItemTransaction @@ -20,7 +18,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import net.minecraft.world.Container import org.bukkit.block.BlockFace @@ -69,8 +66,8 @@ class ItemTransportCache(override val holder: CacheHolder): } } - debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") - debugAudience.information("references: [${itemReferences.entries().joinToString { "${it.key} ${it.value}" }}, ${toVec3i(location)}") +// debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") +// debugAudience.information("references: [${itemReferences.entries().joinToString { "${it.key} ${it.value}" }}, ${toVec3i(location)}") val originNode = getOrCache(location) ?: return @@ -97,7 +94,7 @@ class ItemTransportCache(override val holder: CacheHolder): itemReferences: Multimap, ) { val availableItemReferences = itemReferences[singletonItem] - debugAudience.information("Checking ${singletonItem.type} [$count]") +// debugAudience.information("Checking ${singletonItem.type} [$count]") val destinations: List = getNetworkDestinations(originKey, originNode) { node -> val inventory = destinationInvCache.getOrPut(node.position) { @@ -107,7 +104,7 @@ class ItemTransportCache(override val holder: CacheHolder): LegacyItemUtils.canFit(inventory, singletonItem, 1) }.toList() - if (destinations.isEmpty()) return debugAudience.information("No destinations found") +// if (destinations.isEmpty()) return debugAudience.information("No destinations found") val numDestinations = destinations.size @@ -141,7 +138,7 @@ class ItemTransportCache(override val holder: CacheHolder): for (reference in availableItemReferences) { var destination = getDestination(meta, originKey, validDestinations) - debugAudience.information("Selected destination ${toVec3i(destination)}") +// debugAudience.information("Selected destination ${toVec3i(destination)}") val destinationInventory = destinationInvCache[destination]!! val room = LegacyItemUtils.getSpaceFor(destinationInventory, singletonItem) @@ -162,7 +159,7 @@ class ItemTransportCache(override val holder: CacheHolder): amount ) - debugAudience.highlightBlock(toVec3i(destination), 40L) +// debugAudience.highlightBlock(toVec3i(destination), 40L) } transaction.commit() From a2209dddc725cb6512818f5384aef5b9523d7001 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 17:48:43 -0600 Subject: [PATCH 450/500] Remove sources from destinations --- .../server/features/transport/nodes/cache/ItemTransportCache.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index bc5925acde..001fb6cb1e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -101,7 +101,7 @@ class ItemTransportCache(override val holder: CacheHolder): getInventory(node.position) ?: return@getNetworkDestinations false } - LegacyItemUtils.canFit(inventory, singletonItem, 1) + LegacyItemUtils.canFit(inventory, singletonItem, 1) && availableItemReferences.none { reference -> reference.inventory == inventory } }.toList() // if (destinations.isEmpty()) return debugAudience.information("No destinations found") From f62a618b2a73bc14b71861e68be3e93e0131263c Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 20:40:41 -0600 Subject: [PATCH 451/500] compare block entities rather than craft inventories --- .../server/features/transport/nodes/cache/ItemTransportCache.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 001fb6cb1e..9636a10cec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -101,7 +101,7 @@ class ItemTransportCache(override val holder: CacheHolder): getInventory(node.position) ?: return@getNetworkDestinations false } - LegacyItemUtils.canFit(inventory, singletonItem, 1) && availableItemReferences.none { reference -> reference.inventory == inventory } + LegacyItemUtils.canFit(inventory, singletonItem, 1) && availableItemReferences.none { reference -> (reference.inventory as CraftInventory).inventory == (inventory as CraftInventory).inventory } }.toList() // if (destinations.isEmpty()) return debugAudience.information("No destinations found") From 932e9a252562351f3ab59c3e573a6d1cf4819585 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 21:51:27 -0600 Subject: [PATCH 452/500] Allow pathfinds over the same block up to 6 times --- .../command/misc/TransportDebugCommand.kt | 2 +- .../custom/items/misc/MultimeterItem.kt | 24 ++++++++--- .../nodes/cache/PowerTransportCache.kt | 3 +- .../transport/nodes/cache/TransportCache.kt | 40 +++++++++++++------ .../transport/util/NodePathfinding.kt | 21 ++++++++-- 5 files changed, 65 insertions(+), 25 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index f9279ada41..0f83883149 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -186,7 +186,7 @@ object TransportDebugCommand : SLCommand() { val (_, location) = requireLookingAt(sender) { type.get(it.chunk.ion()) } val chunk = IonChunk.getFromWorldCoordinates(sender.world, getX(location), getZ(location)) ?: fail { "Chunk not loaded" } val grid = type.get(chunk) - if (grid.holder.getExtractorManager().isExtractorPresent(location)) fail { "Extractor not targeted" } +// if (grid.holder.getExtractorManager().isExtractorPresent(location)) fail { "Extractor not targeted" } grid.tickExtractor(location, 1.0, null) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt index 06f20b1c30..4c7067669d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultimeterItem.kt @@ -1,5 +1,6 @@ package net.horizonsend.ion.server.features.custom.items.misc +import it.unimi.dsi.fastutil.longs.Long2IntRBTreeMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.extensions.success @@ -14,6 +15,7 @@ import net.horizonsend.ion.server.features.custom.items.component.Listener.Compa import net.horizonsend.ion.server.features.custom.items.util.ItemFactory import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.MAX_PATHFINDS_OVER_BLOCK import net.horizonsend.ion.server.features.transport.util.PathfindingNodeWrapper import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getHeuristic @@ -30,6 +32,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.updateMeta +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.audience.Audience import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor @@ -75,9 +78,7 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na val targeted = livingEntity.getTargetBlock(null, 10) val key = toBlockKey(targeted.x, targeted.y, targeted.z) - itemStack.updateMeta { - it.persistentDataContainer.set(Z, LONG, key) - } + itemStack.updatePersistentDataContainer { set(Z, LONG, key) } livingEntity.information("Set second point to ${toVec3i(key)}") @@ -139,7 +140,18 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na f = getHeuristic(fromNode, destination) )) - val visited = LongOpenHashSet() + val visited = Long2IntRBTreeMap() + + fun markVisited(node: PathfindingNodeWrapper) { + val pos = node.node.position + val existing = visited.getOrDefault(pos, 0) + + visited[pos] = existing + 1 + } + + fun canVisit(node: Node.NodePositionData): Boolean { + return visited.getOrDefault(node.position, 0) < MAX_PATHFINDS_OVER_BLOCK + } // Safeguard var iterations = 0L @@ -153,14 +165,14 @@ object MultimeterItem : CustomItem("MULTIMETER", Component.text("Multimeter", Na if (current.node.position == destination) return current.buildPath() queueRemove(current) - visited.add(current.node.position) + markVisited(current) val neighbors = getNeighbors(current, { cacheType, world, pos -> getOrCacheNode(cacheType, world, pos) }, null) audience.userError("Found ${neighbors.size} neighbors") for (newNeighbor in neighbors) { audience.information("new neighbor: $newNeighbor at ${toVec3i(newNeighbor.node.position)}") - if (visited.contains(newNeighbor.node.position)) { + if (!canVisit(newNeighbor.node)) { audience.information("conmtinue") continue } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 8073097569..408c2c77d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -28,8 +28,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC tickPowerExtractor(location, delta) } - private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.runTask { - measureOrFallback(TransportDebugCommand.extractorTickTimes) { + private fun tickPowerExtractor(location: BlockKey, delta: Double) = NewTransport.runTask { measureOrFallback(TransportDebugCommand.extractorTickTimes) { val world = holder.getWorld() val sources = getExtractorSourceEntities(location) { it.powerStorage.isEmpty() } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 355b5b6f11..35819fe271 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,16 +1,18 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import com.google.common.collect.TreeBasedTable +import it.unimi.dsi.fastutil.longs.Long2IntRBTreeMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet -import net.horizonsend.ion.server.features.client.display.ClientDisplayEntities.highlightBlock import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.types.ComplexNode import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.MAX_PATHFINDS_OVER_BLOCK import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -23,7 +25,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isAdjacent import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i -import net.horizonsend.ion.server.miscellaneous.utils.debugAudience import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded import net.horizonsend.ion.server.miscellaneous.utils.set import org.bukkit.block.Block @@ -178,18 +179,31 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { inline fun getNetworkDestinations( originPos: BlockKey, originNode: Node, - noinline check: ((Node.NodePositionData) -> Boolean)? = null + noinline check: ((NodePositionData) -> Boolean)? = null ): Collection = getNetworkDestinations(T::class, originPos, originNode, check) fun getNetworkDestinations( clazz: KClass, originPos: BlockKey, originNode: Node, - nodeCheck: ((Node.NodePositionData) -> Boolean)? = null, - nextNodeProvider: Node.NodePositionData.() -> List = { getNextNodes(holder.nodeProvider, null) } + nodeCheck: ((NodePositionData) -> Boolean)? = null, + nextNodeProvider: NodePositionData.() -> List = { getNextNodes(holder.nodeProvider, null) } ): Collection { - val visitQueue = ArrayDeque() - val visited = LongOpenHashSet() + val visitQueue = ArrayDeque() + + val visited = Long2IntRBTreeMap() + + fun markVisited(node: NodePositionData) { + val pos = node.position + val existing = visited.getOrDefault(pos, 0) + + visited[pos] = existing + 1 + } + + fun canVisit(node: NodePositionData): Boolean { + return visited.getOrDefault(node.position, 0) < MAX_PATHFINDS_OVER_BLOCK + } + val destinations = LongOpenHashSet() visitQueue.addAll(originNode.getNextNodes( @@ -200,15 +214,19 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { null )) - while (visitQueue.isNotEmpty()) { + var iterations = 0L + val upperBound = 20_000 + + while (visitQueue.isNotEmpty() && iterations < upperBound) { + iterations++ val current = visitQueue.removeFirst() - visited.add(current.position) + markVisited(current) if (clazz.isInstance(current.type) && (nodeCheck?.invoke(current) != false)) { destinations.add(current.position) } - visitQueue.addAll(nextNodeProvider(current).filterNot { visited.contains(it.position) || visitQueue.contains(it) }) + visitQueue.addAll(nextNodeProvider(current).filterNot { !canVisit(it) || visitQueue.contains(it) }) } return destinations @@ -239,8 +257,6 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { // Traverse network backwards getPreviousNodes(holder.nodeProvider, null) }.forEach { extractorPos -> - debugAudience.highlightBlock(holder.transportManager.getGlobalCoordinate(toVec3i(extractorPos)), 10L) - pathCache.rowMap()[extractorPos]?.keys?.forEach { columnKey -> toRemove.add(extractorPos to columnKey) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index c7dba27077..9f53c90114 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -1,6 +1,6 @@ package net.horizonsend.ion.server.features.transport.util -import it.unimi.dsi.fastutil.ints.IntOpenHashSet +import it.unimi.dsi.fastutil.longs.Long2IntRBTreeMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.nodes.types.Node @@ -19,6 +19,8 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { return type.get(chunk).getOrCache(pos) } +const val MAX_PATHFINDS_OVER_BLOCK = 6 + /** * Uses the A* algorithm to find the shortest available path between these two nodes. **/ @@ -50,7 +52,18 @@ fun getIdealPath( f = getHeuristic(from, destination) )) - val visited = IntOpenHashSet() + val visited = Long2IntRBTreeMap() + + fun markVisited(node: PathfindingNodeWrapper) { + val pos = node.node.position + val existing = visited.getOrDefault(pos, 0) + + visited[pos] = existing + 1 + } + + fun canVisit(node: Node.NodePositionData): Boolean { + return visited.getOrDefault(node.position, 0) < MAX_PATHFINDS_OVER_BLOCK + } // Safeguard var iterations = 0 @@ -63,11 +76,11 @@ fun getIdealPath( if (current.node.position == destination) return current.buildPath() queueRemove(current) - visited.add(current.node.hashCode()) + markVisited(current) // Compute new neighbor data from current position for (computedNeighbor in getNeighbors(current, cachedNodeProvider, pathfindingFilter)) { - if (visited.contains(computedNeighbor.node.hashCode())) continue + if (!canVisit(computedNeighbor.node)) continue // Update the f value computedNeighbor.f = (computedNeighbor.g + getHeuristic(computedNeighbor.node, destination)) From 79d3b7fe06e6e23823fc30d32d7fbbc795aea1f9 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:04:07 -0600 Subject: [PATCH 453/500] Fix pilot exception --- .../ion/server/features/transport/nodes/types/PowerNode.kt | 5 +++-- .../horizonsend/ion/server/miscellaneous/utils/Blocks.kt | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt index 39e71e6456..1fbbd2f686 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/PowerNode.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.RollingAverage import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.axis +import net.horizonsend.ion.server.miscellaneous.utils.axisOrNull import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.faces @@ -34,8 +35,8 @@ sealed interface PowerNode : Node { data class EndRodNode(var axis: Axis) : PowerNode, ComplexNode { override val pathfindingResistance: Double = 0.5 - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset.axis == this.axis + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset.axisOrNull == this.axis + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset.axisOrNull == this.axis override fun getTransferableDirections(backwards: BlockFace): Set = setOf(backwards.oppositeFace) override fun displace(movement: StarshipMovement) { this.axis = movement.displaceFace(this.axis.faces.first).axis diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt index 895fda1ab9..e3e684b004 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Blocks.kt @@ -128,12 +128,14 @@ val BlockFace.leftFace: BlockFace else -> error("Unsupported direction $this") } -val BlockFace.axis: Axis +val BlockFace.axis: Axis get() = this.axisOrNull ?: error("Unsupported axis for BlockFace: $this") + +val BlockFace.axisOrNull: Axis? get() = when (this) { BlockFace.NORTH, BlockFace.SOUTH -> Axis.Z BlockFace.EAST, BlockFace.WEST -> Axis.X BlockFace.UP, BlockFace.DOWN -> Axis.Y - else -> error("Unsupported axis for BlockFace: $this") + else -> null } val Axis.faces: Pair From 959a1d238cb17d0631397f13df1589066bf65dcf Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:07:13 -0600 Subject: [PATCH 454/500] Setpower from signs --- .../ion/server/command/qol/SetPowerCommand.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt index b5d42da9c3..2ec09d4e67 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt @@ -11,6 +11,7 @@ import net.horizonsend.ion.server.command.admin.debug import net.horizonsend.ion.server.features.multiblock.MultiblockEntities import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity import net.horizonsend.ion.server.miscellaneous.utils.getSelection +import org.bukkit.block.data.type.WallSign import org.bukkit.entity.Player @CommandAlias("setpower") @@ -39,6 +40,16 @@ object SetPowerCommand : SLCommand() { sender.debug("checking block at $x $y $z") + val data = sender.world.getBlockData(x, y, z) + if (data is WallSign) { + val entity = MultiblockEntities.getMultiblockEntity(x, y, z, sender.world, data) + + if (entity is PoweredMultiblockEntity) { + entity.powerStorage.setPower(amount) + hits++ + } + } + val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) if (entity !is PoweredMultiblockEntity) continue From 1b256ab92988caad23459f32e93269176fe061ae Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:14:33 -0600 Subject: [PATCH 455/500] Subtract common minimum resistance --- .../features/transport/nodes/cache/PowerTransportCache.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 408c2c77d6..06a307ea24 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -122,11 +122,13 @@ class PowerTransportCache(holder: CacheHolder) : TransportC } } var maximumResistance: Double = -1.0 + var minimumResistance = 0.0 // Perform the calc & max find in the same loop val pathResistance: Array = Array(numDestinations) { val res = paths[it]?.resistance if (res != null && maximumResistance < res) maximumResistance = res + if (res != null && minimumResistance > res) minimumResistance = res res } @@ -140,7 +142,7 @@ class PowerTransportCache(holder: CacheHolder) : TransportC val sortedIndexes = getSorted(pathResistance) val shareFactors: Array = Array(numDestinations) { index -> - val resistance = pathResistance[index] ?: return@Array null + val resistance = (pathResistance[index] ?: return@Array null) - minimumResistance val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) shareFactorSum += fac From dfa93e530293874e0c38f492a4d4d6b3d0701e8f Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:20:34 -0600 Subject: [PATCH 456/500] prevent double hits --- .../ion/server/command/qol/SetPowerCommand.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt index 2ec09d4e67..3c7491d6df 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/qol/SetPowerCommand.kt @@ -31,7 +31,7 @@ object SetPowerCommand : SLCommand() { if (sender.world.name != selection.world?.name) return - var hits = 0 + val entities = mutableSetOf() for (blockPosition in selection) { val x = blockPosition.x() @@ -45,20 +45,20 @@ object SetPowerCommand : SLCommand() { val entity = MultiblockEntities.getMultiblockEntity(x, y, z, sender.world, data) if (entity is PoweredMultiblockEntity) { - entity.powerStorage.setPower(amount) - hits++ + entities.add(entity) } } val entity = MultiblockEntities.getMultiblockEntity(sender.world, x, y ,z) if (entity !is PoweredMultiblockEntity) continue - entity.powerStorage.setPower(amount) - hits++ + entities.add(entity) + } - sender.debug("power sent") + entities.forEach { entity -> + entity.powerStorage.setPower(amount) } - sender.success("Set power to $amount in $hits multiblocks.") + sender.success("Set power to $amount in ${entities.size} multiblocks.") } } From 31f5ccfeb27c1c4c1ec97541f4131c909fdaac42 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 31 Jan 2025 10:52:09 -0600 Subject: [PATCH 457/500] handle double chests --- .../nodes/cache/ItemTransportCache.kt | 66 ++++++++++++++++++- .../transport/nodes/types/ItemNode.kt | 8 +++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 9636a10cec..38f426c8bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -15,13 +15,22 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getBlockEntity import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils +import net.horizonsend.ion.server.miscellaneous.utils.blockFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe import net.horizonsend.ion.server.miscellaneous.utils.multimapOf +import net.minecraft.world.CompoundContainer import net.minecraft.world.Container +import net.minecraft.world.level.block.ChestBlock +import net.minecraft.world.level.block.DoubleBlockCombiner +import net.minecraft.world.level.block.entity.ChestBlockEntity +import net.minecraft.world.level.block.state.properties.ChestType import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.inventory.CraftInventory +import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass @@ -174,9 +183,62 @@ class ItemTransportCache(override val holder: CacheHolder): return destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } } + companion object { + private val CHEST_COMBINER = object : DoubleBlockCombiner.Combiner { + override fun acceptDouble(p0: ChestBlockEntity, p1: ChestBlockEntity): Int { + return 2 + } + + override fun acceptSingle(p0: ChestBlockEntity): Int { + return 1 + } + + override fun acceptNone(): Int { + return 0 + } + } + } + + /** + * Gets a live inventory. + * RETURNED INVENTORIES SHOULD NOT BE MODIFIED ASYNC + **/ fun getInventory(localKey: BlockKey): CraftInventory? { - val tileEntity = getBlockEntity(holder.transportManager.getGlobalCoordinate(toVec3i(localKey)), holder.getWorld()) as? Container ?: return null - return CraftInventory(tileEntity) + val global = holder.transportManager.getGlobalCoordinate(toVec3i(localKey)) + + val state = getNMSBlockSateSafe(holder.getWorld(), global.x, global.y, global.z) ?: return null + val entity = getBlockEntity(global, holder.getWorld()) as? Container ?: return null + + return when (state.block) { + is ChestBlock -> { + val type = state.getValue(ChestBlock.TYPE) + + if (type == ChestType.SINGLE) { + return CraftInventory(entity) + } + + val relativeFace = when (type) { + // If it is on the left, need to look right, vice versa + ChestType.LEFT -> RelativeFace.RIGHT + ChestType.RIGHT -> RelativeFace.LEFT + else -> error("Single condition already matched") + } + + val direction = state.getValue(ChestBlock.FACING) + val otherPos = global.getRelative(relativeFace[direction.blockFace]) + + val otherEntity = getBlockEntity(otherPos, holder.getWorld()) as? Container + + if (otherEntity == null) { + return CraftInventory(entity) + } + + return CraftInventoryDoubleChest(CompoundContainer(entity, otherEntity)) + } + else -> { + CraftInventory(entity) + } + } } fun getSources(extractorLocation: BlockKey): Set { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 80c198a9e8..20124e695a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -5,6 +5,7 @@ import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.PipeChannel.entries import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData @@ -13,12 +14,14 @@ import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.horizonsend.ion.server.miscellaneous.utils.getBlockDataSafe import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextColor.fromHexString import org.bukkit.Material import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import java.lang.ref.WeakReference @@ -32,6 +35,11 @@ interface ItemNode : Node { override fun getTransferableDirections(backwards: BlockFace): Set = setOf() override val pathfindingResistance: Double = 0.0 + + fun getBlockData(holder: CacheHolder<*>): BlockData? { + val (x, y, z) = holder.transportManager.getGlobalCoordinate(toVec3i(position)) + return getBlockDataSafe(holder.getWorld(), x, y, z) + } } data object ItemExtractorNode : ItemNode { From 417cb773ff147fe1d5714aeb546d0a16400f7a4b Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:10:18 -0600 Subject: [PATCH 458/500] prevent double chest self transfer --- .../items/transaction/ItemReference.kt | 4 ++-- .../nodes/cache/ItemTransportCache.kt | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt index 5fcd9c45d8..aa5c426370 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/transaction/ItemReference.kt @@ -1,10 +1,10 @@ package net.horizonsend.ion.server.features.transport.items.transaction -import org.bukkit.inventory.Inventory +import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.inventory.ItemStack data class ItemReference( - val inventory: Inventory, + val inventory: CraftInventory, val index: Int ) { fun get(): ItemStack? = inventory.getItem(index) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 38f426c8bf..9b28ea08f4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -31,7 +31,6 @@ import net.minecraft.world.level.block.state.properties.ChestType import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest -import org.bukkit.inventory.Inventory import org.bukkit.inventory.ItemStack import kotlin.reflect.KClass @@ -80,7 +79,7 @@ class ItemTransportCache(override val holder: CacheHolder): val originNode = getOrCache(location) ?: return - val destinationInvCache = mutableMapOf() + val destinationInvCache = mutableMapOf() for ((item, count) in byCount) transferItemType( location, @@ -99,7 +98,7 @@ class ItemTransportCache(override val holder: CacheHolder): meta: ItemExtractorMetaData?, singletonItem: ItemStack, count: Int, - destinationInvCache: MutableMap, + destinationInvCache: MutableMap, itemReferences: Multimap, ) { val availableItemReferences = itemReferences[singletonItem] @@ -110,7 +109,18 @@ class ItemTransportCache(override val holder: CacheHolder): getInventory(node.position) ?: return@getNetworkDestinations false } - LegacyItemUtils.canFit(inventory, singletonItem, 1) && availableItemReferences.none { reference -> (reference.inventory as CraftInventory).inventory == (inventory as CraftInventory).inventory } + if (!LegacyItemUtils.canFit(inventory, singletonItem, 1)) return@getNetworkDestinations false + + availableItemReferences.none { reference -> + if (inventory is CraftInventoryDoubleChest) { + val leftMatches = reference.inventory.inventory == (inventory.leftSide as CraftInventory).inventory + val rightMatches = reference.inventory.inventory == (inventory.rightSide as CraftInventory).inventory + + return@getNetworkDestinations leftMatches || rightMatches + } + + reference.inventory.inventory == inventory.inventory + } }.toList() // if (destinations.isEmpty()) return debugAudience.information("No destinations found") From d37db273588961b930136e57c02b468eda67aac3 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 31 Jan 2025 12:25:02 -0600 Subject: [PATCH 459/500] code cleanup, ensure left chest halves are correct regardless of origin chest --- .../nodes/cache/ItemTransportCache.kt | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 9b28ea08f4..3b80fb78c7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -1,6 +1,5 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import com.google.common.collect.Multimap import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.command.misc.TransportDebugCommand.measureOrFallback import net.horizonsend.ion.server.features.transport.NewTransport @@ -15,13 +14,13 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.getBlockEntity import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.blockFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getNMSBlockSateSafe -import net.horizonsend.ion.server.miscellaneous.utils.multimapOf import net.minecraft.world.CompoundContainer import net.minecraft.world.Container import net.minecraft.world.level.block.ChestBlock @@ -56,37 +55,29 @@ class ItemTransportCache(override val holder: CacheHolder): return } - val byInventory: Map>> = sources.associateWith { stacks -> stacks.withIndex().filter { (_, value) -> value != null } } - if (byInventory.isEmpty()) return + val references = mutableMapOf>() - val byCount = mutableMapOf() - val itemReferences = multimapOf() + for (inventory in sources) { + val items = inventory.contents.withIndex() - for ((inventory, items) in byInventory) { - for ((index, item) in items) { - val asOne = item.asOne() + for ((index, item: ItemStack?) in items) { + if (item == null) continue - itemReferences[asOne].add(ItemReference(inventory, index)) - - if (byCount.containsKey(asOne)) continue - val count = items.sumOf { stack -> if (stack.value.isSimilar(item)) stack.value.amount else 0 } - byCount[asOne] = count + references.getOrPut(item.asOne()) { ArrayDeque() }.add(ItemReference(inventory, index)) } } -// debugAudience.information("counts: [${byCount.entries.joinToString { "${it.key.type}, ${it.value}]" }}, ${toVec3i(location)}") -// debugAudience.information("references: [${itemReferences.entries().joinToString { "${it.key} ${it.value}" }}, ${toVec3i(location)}") +// debugAudience.information("references: [${references.entries.joinToString { "${it.key} ${it.value}" }}, ${toVec3i(location)}") val originNode = getOrCache(location) ?: return val destinationInvCache = mutableMapOf() - for ((item, count) in byCount) transferItemType( + for ((item, itemReferences) in references) transferItemType( location, originNode, meta, item, - count, destinationInvCache, itemReferences ) @@ -97,37 +88,36 @@ class ItemTransportCache(override val holder: CacheHolder): originNode: Node, meta: ItemExtractorMetaData?, singletonItem: ItemStack, - count: Int, destinationInvCache: MutableMap, - itemReferences: Multimap, + availableItemReferences: ArrayDeque, ) { - val availableItemReferences = itemReferences[singletonItem] // debugAudience.information("Checking ${singletonItem.type} [$count]") val destinations: List = getNetworkDestinations(originKey, originNode) { node -> - val inventory = destinationInvCache.getOrPut(node.position) { + val destinationInventory = destinationInvCache.getOrPut(node.position) { getInventory(node.position) ?: return@getNetworkDestinations false } - if (!LegacyItemUtils.canFit(inventory, singletonItem, 1)) return@getNetworkDestinations false + if (!LegacyItemUtils.canFit(destinationInventory, singletonItem, 1)) { + return@getNetworkDestinations false + } - availableItemReferences.none { reference -> - if (inventory is CraftInventoryDoubleChest) { - val leftMatches = reference.inventory.inventory == (inventory.leftSide as CraftInventory).inventory - val rightMatches = reference.inventory.inventory == (inventory.rightSide as CraftInventory).inventory + availableItemReferences.none { itemReference -> + val referenceInventory = itemReference.inventory + if (destinationInventory is CraftInventoryDoubleChest && referenceInventory is CraftInventoryDoubleChest) { + val leftMatches = (referenceInventory.leftSide as CraftInventory).inventory == (destinationInventory.leftSide as CraftInventory).inventory + val rightMatches = (referenceInventory.rightSide as CraftInventory).inventory == (destinationInventory.rightSide as CraftInventory).inventory - return@getNetworkDestinations leftMatches || rightMatches + return@none leftMatches || rightMatches } - reference.inventory.inventory == inventory.inventory + referenceInventory.inventory == destinationInventory.inventory } }.toList() // if (destinations.isEmpty()) return debugAudience.information("No destinations found") - val numDestinations = destinations.size - - val paths: Array = Array(numDestinations) { + val paths: Array = Array(destinations.size) { findPath( origin = Node.NodePositionData( ItemNode.ItemExtractorNode, @@ -181,7 +171,9 @@ class ItemTransportCache(override val holder: CacheHolder): // debugAudience.highlightBlock(toVec3i(destination), 40L) } - transaction.commit() + Tasks.sync { + transaction.commit() + } } fun getDestination(meta: ItemExtractorMetaData?, extractorKey: BlockKey, destinations: List): BlockKey { @@ -243,7 +235,14 @@ class ItemTransportCache(override val holder: CacheHolder): return CraftInventory(entity) } - return CraftInventoryDoubleChest(CompoundContainer(entity, otherEntity)) + if (otherEntity == entity) { + // Idk, just in case + return CraftInventory(entity) + } + + val left = if (type == ChestType.LEFT) entity else otherEntity + val right = if (type == ChestType.RIGHT) entity else otherEntity + return CraftInventoryDoubleChest(CompoundContainer(left, right)) } else -> { CraftInventory(entity) From 69d0ebd94933b730710788856b89d1b66fdf16cb Mon Sep 17 00:00:00 2001 From: kwazedilla Date: Thu, 30 Jan 2025 16:50:50 -0800 Subject: [PATCH 460/500] WIP: First pass at multiblock descriptions --- .../multiblock/type/ammo/AmmoLoaderMultiblock.kt | 10 +++++++++- .../multiblock/type/ammo/AmmoPressMultiblock.kt | 8 +++++++- .../multiblock/type/ammo/MissileLoaderMultiblock.kt | 10 +++++++++- .../type/defense/passive/areashield/AreaShield.kt | 10 +++++++++- .../multiblock/type/fluid/CanisterVentMultiblock.kt | 9 ++++++++- .../multiblock/type/fluid/GasPowerPlantMultiblock.kt | 8 +++++++- .../fluid/collector/CanisterGasCollectorMultiblock.kt | 10 +++++++++- .../fluid/collector/PipedGasCollectorMultiblock.kt | 9 ++++++++- .../multiblock/type/industry/CentrifugeMultiblock.kt | 10 +++++++++- .../multiblock/type/industry/CircuitfabMultiblock.kt | 10 +++++++++- .../multiblock/type/industry/CompressorMultiblock.kt | 10 +++++++++- .../multiblock/type/industry/FabricatorMultiblock.kt | 10 +++++++++- .../multiblock/type/industry/GasFurnaceMultiblock.kt | 10 +++++++++- .../multiblock/type/industry/PlatePressMultiblock.kt | 10 +++++++++- .../features/multiblock/type/misc/MobDefender.kt | 10 +++++++++- .../multiblock/type/printer/ArmorPrinterMultiblock.kt | 6 ++++++ .../type/printer/CarbonPrinterMultiblock.kt | 6 ++++++ .../type/printer/CarbonProcessorMultiblock.kt | 8 +++++++- .../multiblock/type/printer/GlassPrinterMultiblock.kt | 6 ++++++ .../multiblock/type/printer/PrinterMultiblock.kt | 3 ++- .../type/printer/TechnicalPrinterMultiblock.kt | 7 ++++++- .../starship/mininglasers/MiningLaserMultiblock.kt | 11 ++++++++++- .../cannon/LaserCannonStarshipWeaponMultiblock.kt | 10 +++++++++- .../cannon/PlasmaCannonStarshipWeaponMultiblock.kt | 10 +++++++++- .../cannon/PulseCannonStarshipWeaponMultiblock.kt | 10 +++++++++- .../heavy/HeavyLaserStarshipWeaponMultiblock.kt | 10 +++++++++- .../weapon/heavy/TorpedoStarshipWeaponMultiblock.kt | 10 +++++++++- .../misc/PointDefenseStarshipWeaponMultiblock.kt | 10 +++++++++- .../type/starship/weapon/turret/TurretMultiblock.kt | 10 +++++++++- 29 files changed, 235 insertions(+), 26 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 93b6304ad4..11591ca913 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -5,12 +5,15 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.IndustryEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock { +object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -131,6 +134,11 @@ object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock { +abstract class AmmoPressMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { + override val displayName: Component + get() = text("Ammo Press") + override val description: Component + get() = text("Refills Blasters and Magazines with various ammunition refills.") override fun MultiblockShape.buildStructure() { z(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index b6133a4e24..e14bdd6703 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -5,12 +5,15 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.IndustryEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -object MissileLoaderMultiblock : Multiblock(), EntityMultiblock { +object MissileLoaderMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -133,6 +136,11 @@ object MissileLoaderMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { +abstract class AreaShield(val radius: Int) : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { override fun onTransformSign(player: Player, sign: Sign) { player.success("Area Shield created.") } + override val displayName: Component + get() = text("Area Shield (Radius $radius)") + override val description: Component + get() = text("Prevents explosions within a $radius radius.") + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { val blocks: List = getSphereBlocks(radius) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt index d69f19e6c8..232c456104 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/fluid/CanisterVentMultiblock.kt @@ -11,16 +11,18 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTi import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.fluid.collector.CanisterGasCollectorMultiblock import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.inventory.FurnaceInventory -object CanisterVentMultiblock : Multiblock(), EntityMultiblock { +object CanisterVentMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "vent" override val signText: Array = arrayOf( @@ -33,6 +35,11 @@ object CanisterVentMultiblock : Multiblock(), EntityMultiblock { +object GasPowerPlantMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "gaspowerplant" override val signText: Array = arrayOf( @@ -46,6 +47,11 @@ object GasPowerPlantMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock { +object CanisterGasCollectorMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { override val name = "gascollector" override val signText = createSignText( @@ -47,6 +50,11 @@ object CanisterGasCollectorMultiblock : Multiblock(), EntityMultiblock, - InteractableMultiblock { + InteractableMultiblock, + DisplayNameMultilblock { override val name: String = "gascollector" + override val displayName: Component + get() = text("Piped Gas Collector") + override val description: Component + get() = text("Fills itself with random gases on this planet.") + override val signText: Array = arrayOf( ofChildren(text("Gas ", RED), text("Collector", GOLD)), null, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index 1a0284e40d..c9f4a6904d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -5,12 +5,15 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.type.power.IndustryEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.World import org.bukkit.block.BlockFace -object CentrifugeMultiblock : Multiblock(), EntityMultiblock { +object CentrifugeMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "centrifuge" override val signText = createSignText( @@ -20,6 +23,11 @@ object CentrifugeMultiblock : Multiblock(), EntityMultiblock { +object CircuitfabMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "circuitfab" override val signText = createSignText( @@ -20,6 +23,11 @@ object CircuitfabMultiblock : Multiblock(), EntityMultiblock { +object CompressorMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "compressor" override val signText = createSignText( @@ -20,6 +23,11 @@ object CompressorMultiblock : Multiblock(), EntityMultiblock { +object FabricatorMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "fabricator" override val signText = createSignText( @@ -21,6 +24,11 @@ object FabricatorMultiblock : Multiblock(), EntityMultiblock { +object GasFurnaceMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "gasfurnace" override val signText = createSignText( @@ -19,6 +22,11 @@ object GasFurnaceMultiblock : Multiblock(), EntityMultiblock { +object PlatePressMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { @@ -107,6 +110,11 @@ object PlatePressMultiblock : Multiblock(), EntityMultiblock { +object MobDefender : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "mobdefender" override val signText = createSignText( @@ -26,6 +29,11 @@ object MobDefender : Multiblock(), EntityMultiblock { +object CarbonProcessorMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "processor" override val signText = createSignText( @@ -37,6 +39,10 @@ object CarbonProcessorMultiblock : Multiblock(), EntityMultiblock { +abstract class PrinterMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "printer" abstract fun getOutput(product: Material): ItemStack abstract val mirrored: Boolean diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt index b9b0c5be14..1febade68f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/printer/TechnicalPrinterMultiblock.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.printer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.inventory.ItemStack @@ -11,7 +13,10 @@ abstract class AbstractTechnicalPrinterMultiblock : PrinterMultiblock() { "", "&7+?[-|],+" ) - + override val displayName: Component + get() = text("Technical Printer") + override val description: Component + get() = text("Transforms Cobblestone into Sponge.") override fun getOutput(product: Material) = ItemStack(product, 1) override fun MultiblockShape.RequirementBuilder.printerMachineryBlock() = redstoneLamp() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt index 2a60df0903..f6a9225546 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblock.kt @@ -1,18 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.SimplePoweredEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.empty +import net.kyori.adventure.text.Component.text import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.inventory.Inventory -abstract class MiningLaserMultiblock : Multiblock(), EntityMultiblock { +abstract class MiningLaserMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name = "mininglaser" abstract val range: Double @@ -27,6 +33,9 @@ abstract class MiningLaserMultiblock : Multiblock(), EntityMultiblock() { +object LaserCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): LaserCannonWeaponSubsystem { return LaserCannonWeaponSubsystem(starship, pos, face) } + override val displayName: Component + get() = text("Laser Cannon") + override val description: Component + get() = text("A low-power starship weapon.") + override fun MultiblockShape.buildStructure() { at(+0, +0, +0).sponge() at(+0, +0, +1).pistonBase() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt index 91de06a48e..26c92a19fc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PlasmaCannonStarshipWeaponMultiblock.kt @@ -1,17 +1,25 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PlasmaCannonWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace -object PlasmaCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +object PlasmaCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): PlasmaCannonWeaponSubsystem { return PlasmaCannonWeaponSubsystem(starship, pos, face) } + override val displayName: Component + get() = text("Plasma Cannon") + override val description: Component + get() = text("A high-power starship weapon useful on smaller starships.") + override fun MultiblockShape.buildStructure() { at(+0, +0, +0).sponge() at(+0, +0, +1).ironBlock() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt index ff73c0064d..8421f959e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/cannon/PulseCannonStarshipWeaponMultiblock.kt @@ -1,17 +1,25 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.cannon import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PulseCannonWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace -object PulseCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +object PulseCannonStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): PulseCannonWeaponSubsystem { return PulseCannonWeaponSubsystem(starship, pos, face) } + override val displayName: Component + get() = text("Pulse Cannon") + override val description: Component + get() = text("A weapon designed to destroy small starships. Only mountable on Gunship and Frigate.") + override fun MultiblockShape.buildStructure() { at(+0, +0, +0).sponge() at(+0, +0, +1).anyGlass() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt index 1e945a38b8..47816ed8d7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt @@ -1,17 +1,25 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.HeavyLaserWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace -object HeavyLaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +object HeavyLaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): HeavyLaserWeaponSubsystem { return HeavyLaserWeaponSubsystem(starship, pos, face) } + override val displayName: Component + get() = text("Heavy Laser") + override val description: Component + get() = text("A heavy weapon with a homing projectile. Slows down small ships on impact if the firing ship is also small.") + override fun MultiblockShape.buildStructure() { repeat(+7) { z -> z(z) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt index 7b11ce6f86..002cf1f86f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/TorpedoStarshipWeaponMultiblock.kt @@ -1,17 +1,25 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TorpedoWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace -object TorpedoStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +object TorpedoStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): TorpedoWeaponSubsystem { return TorpedoWeaponSubsystem(starship, pos, face) } + override val displayName: Component + get() = text("Torpedo") + override val description: Component + get() = text("A heavy weapon with a homing projectile.") + override fun MultiblockShape.buildStructure() { at(+0, +0, +0).sponge() at(+0, +0, +1).sponge() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt index 4b9a6484d1..f295abaf63 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt @@ -1,18 +1,26 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.misc import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.PointDefenseSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace -sealed class PointDefenseStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +sealed class PointDefenseStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): PointDefenseSubsystem { val adjustedFace = getAdjustedFace(face) return PointDefenseSubsystem(starship, pos, adjustedFace) } + override val displayName: Component + get() = text("Point Defense Turret") + override val description: Component + get() = text("An automatic-only weapon effective against players and entities.") + protected abstract fun getAdjustedFace(originalFace: BlockFace): BlockFace } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt index 5f791644e8..081d90025b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt @@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.configuration.StarshipWeapons import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.MultiblockAccess +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.SubsystemMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.active.ActiveStarships @@ -17,6 +18,8 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.minecraft.world.level.block.Rotation import org.bukkit.Location import org.bukkit.Material @@ -30,7 +33,7 @@ import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin -abstract class TurretMultiblock : Multiblock(), SubsystemMultiblock { +abstract class TurretMultiblock : Multiblock(), SubsystemMultiblock, DisplayNameMultilblock { init { shape.signCentered() shape.ignoreDirection() @@ -39,6 +42,11 @@ abstract class TurretMultiblock : Multiblock(), SubsystemMultiblock Date: Fri, 31 Jan 2025 10:58:42 -0800 Subject: [PATCH 461/500] WIP: more progress on names and desc (formatting fixes, colored tier text, mining laser fixes) --- .../type/ammo/AmmoLoaderMultiblock.kt | 6 ++--- .../type/ammo/AmmoPressMultiblock.kt | 6 ++--- .../type/ammo/MissileLoaderMultiblock.kt | 6 ++--- .../type/autocrafter/AutoCrafterMultiblock.kt | 1 + .../farming/harvester/HarvesterMultiblock.kt | 8 +++--- .../type/farming/planter/PlanterMultiblock.kt | 8 +++--- .../type/industry/CentrifugeMultiblock.kt | 6 ++--- .../type/industry/CircuitfabMultiblock.kt | 6 ++--- .../type/industry/CompressorMultiblock.kt | 6 ++--- .../type/industry/FabricatorMultiblock.kt | 6 ++--- .../type/industry/GasFurnaceMultiblock.kt | 6 ++--- .../type/industry/PlatePressMultiblock.kt | 6 ++--- .../type/misc/DisposalMultiblock.kt | 3 ++- .../power/generator/GeneratorMultiblock.kt | 4 ++- .../powerfurnace/PowerFurnaceMultiblock.kt | 4 ++- .../type/printer/ArmorPrinterMultiblock.kt | 7 +++--- .../type/printer/CarbonPrinterMultiblock.kt | 7 +++--- .../type/printer/CarbonProcessorMultiblock.kt | 6 ++--- .../type/printer/GlassPrinterMultiblock.kt | 7 +++--- .../printer/TechnicalPrinterMultiblock.kt | 7 +++--- .../mininglasers/MiningLaserMultiblock.kt | 8 ------ .../MiningLaserMultiblockTier1.kt | 16 +++++++++--- .../MiningLaserMultiblockTier2.kt | 25 +++++++++++++------ .../MiningLaserMultiblockTier3.kt | 25 +++++++++++++------ .../MiningLaserMultiblockTier4.kt | 25 +++++++++++++------ 25 files changed, 118 insertions(+), 97 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt index 11591ca913..d435e8f53b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/AmmoLoaderMultiblock.kt @@ -134,10 +134,8 @@ object AmmoLoaderMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { - override val displayName: Component - get() = text("Ammo Press") - override val description: Component - get() = text("Refills Blasters and Magazines with various ammunition refills.") + override val displayName: Component get() = text("Ammo Press") + override val description: Component get() = text("Refills Blasters and Magazines with various ammunition refills.") override fun MultiblockShape.buildStructure() { z(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt index e14bdd6703..ac4e093ee1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/ammo/MissileLoaderMultiblock.kt @@ -136,10 +136,8 @@ object MissileLoaderMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "harvester" + val nameText = ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)) + val tierText = ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, tierColor)) override val signText: Array = arrayOf( - ofChildren(text("Auto ", GRAY), text("Harvester", GREEN)), - ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, tierColor)), + nameText, + tierText, null, null ) - override val displayName: Component = text("Tier $tierNumber Harvester") + override val displayName: Component = ofChildren(tierText, nameText) override val description: Component get() = text("Harvests crops. Crops will be harvested opposite of the sign, up to $regionDepth blocks away.") val powerPerCrop: Int = 10 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index ee9a365d71..9aed3f0f1a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -35,14 +35,16 @@ import org.bukkit.inventory.FurnaceInventory abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int, tierColor: TextColor) : Multiblock(), EntityMultiblock, DisplayNameMultilblock { override val name: String = "planter" + private val nameText = ofChildren(text("Auto ", GRAY), text("Planter", GREEN)) + val tierText = ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, tierColor)) override val signText: Array = arrayOf( - ofChildren(text("Auto ", GRAY), text("Planter", GREEN)), - ofChildren(text("Tier ", DARK_AQUA), text(tierNumber, tierColor)), + nameText, + tierText, null, null ) - override val displayName: Component = text("Tier $tierNumber Planter") + override val displayName: Component = ofChildren(tierText, nameText) override val description: Component get() = text("Plants crops on farmland. Crops will be planted opposite of the sign, up to $regionDepth blocks away.") abstract val regionDepth: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt index c9f4a6904d..004b407f36 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/industry/CentrifugeMultiblock.kt @@ -23,10 +23,8 @@ object CentrifugeMultiblock : Multiblock(), EntityMultiblock = arrayOf( text("Mining ").color(DARK_GRAY).append(text("Laser").color(GREEN)), - text("Tier 1").color(NamedTextColor.AQUA), + tierText, text(""), text("") ) @@ -21,16 +23,19 @@ sealed class MiningLaserMultiblockTier1 : MiningLaserMultiblock() { override val maxPower: Int = 100000 override val beamOrigin = Triple(0, 3, 1) - override val range: Double = 75.0 - override val mineRadius = 4 + final override val range: Double = 75.0 + final override val mineRadius = 4 override val beamCount: Int = 1 override val maxBroken: Int = 6 override val sound: String = "horizonsend:starship.weapon.mining_laser.t1_loop" override val tier: Int = 1 + + override val description: Component = text("Emits a beam $range blocks long that breaks blocks in a $mineRadius block radius.") } object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top)")) override val side = BlockFace.UP override val outputOffset: Vec3i = Vec3i(-1, -1, 0) @@ -110,6 +115,7 @@ object MiningLaserMultiblockTier1Top : MiningLaserMultiblockTier1() { } object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top) (Mirrored)")) override val side = BlockFace.UP override val outputOffset: Vec3i = Vec3i(+1, -1, 0) @@ -190,6 +196,7 @@ object MiningLaserMultiblockTier1TopMirrored : MiningLaserMultiblockTier1() { } object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -3, +1) @@ -271,6 +278,7 @@ object MiningLaserMultiblockTier1Bottom : MiningLaserMultiblockTier1() { } object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom) (Mirrored)")) override val side = BlockFace.DOWN override val outputOffset: Vec3i = Vec3i(+1, +1, 0) @@ -352,6 +360,7 @@ object MiningLaserMultiblockTier1BottomMirrored : MiningLaserMultiblockTier1() { } object MiningLaserMultiblockTier1Side : MiningLaserMultiblockTier1() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, +5) @@ -436,6 +445,7 @@ object MiningLaserMultiblockTier1Side : MiningLaserMultiblockTier1() { } object MiningLaserMultiblockTier1SideMirrored : MiningLaserMultiblockTier1() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side) (Mirrored)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, -5) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt index 2d644e89a8..310082fbb6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier2.kt @@ -1,32 +1,38 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace sealed class MiningLaserMultiblockTier2 : MiningLaserMultiblock() { + val tierText = text("Tier 2").color(NamedTextColor.AQUA) override val signText: Array = arrayOf( - Component.text("Mining ").color(NamedTextColor.DARK_GRAY) - .append(Component.text("Laser").color(NamedTextColor.GREEN)), - Component.text("Tier 2").color(NamedTextColor.AQUA), - Component.text(""), - Component.text("") + text("Mining ").color(NamedTextColor.DARK_GRAY) + .append(text("Laser").color(NamedTextColor.GREEN)), + tierText, + text(""), + text("") ) override val maxPower: Int = 300000 override val beamOrigin = Triple(0, 3, 1) - override val range: Double = 110.0 - override val mineRadius = 5 + final override val range: Double = 110.0 + final override val mineRadius = 5 override val beamCount: Int = 3 override val maxBroken: Int = 7 override val sound: String = "horizonsend:starship.weapon.mining_laser.t2_loop" override val tier: Int = 2 + + override val description: Component = text("Emits a beam $range blocks long that breaks blocks in a $mineRadius block radius.") } object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +5, +1) @@ -142,6 +148,7 @@ object MiningLaserMultiblockTier2Top : MiningLaserMultiblockTier2() { } object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top) (Mirrored)")) override val side = BlockFace.UP override val outputOffset: Vec3i = Vec3i(+1, -1, 0) @@ -258,6 +265,7 @@ object MiningLaserMultiblockTier2TopMirrored : MiningLaserMultiblockTier2() { } object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -5, +1) @@ -373,6 +381,7 @@ object MiningLaserMultiblockTier2Bottom : MiningLaserMultiblockTier2() { } object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom) (Mirrored)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -5, -2) @@ -488,6 +497,7 @@ object MiningLaserMultiblockTier2BottomMirrored : MiningLaserMultiblockTier2() { } object MiningLaserMultiblockTier2Side : MiningLaserMultiblockTier2() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +0, +7) @@ -607,6 +617,7 @@ object MiningLaserMultiblockTier2Side : MiningLaserMultiblockTier2() { } object MiningLaserMultiblockTier2SideMirrored : MiningLaserMultiblockTier2() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side) (Mirrored)")) override val side = BlockFace.UP override val outputOffset: Vec3i = Vec3i(+1, -1, 0) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt index b0caed8531..781fcbf7d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier3.kt @@ -1,32 +1,38 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace sealed class MiningLaserMultiblockTier3 : MiningLaserMultiblock() { + val tierText = text("Tier 3").color(NamedTextColor.AQUA) override val signText: Array = arrayOf( - Component.text("Mining ").color(NamedTextColor.DARK_GRAY) - .append(Component.text("Laser").color(NamedTextColor.GREEN)), - Component.text("Tier 3").color(NamedTextColor.AQUA), - Component.text(""), - Component.text("") + text("Mining ").color(NamedTextColor.DARK_GRAY) + .append(text("Laser").color(NamedTextColor.GREEN)), + tierText, + text(""), + text("") ) override val maxPower: Int = 500000 override val beamOrigin = Triple(0, 3, 1) - override val range: Double = 170.0 - override val mineRadius = 7 + final override val range: Double = 170.0 + final override val mineRadius = 7 override val beamCount: Int = 6 override val maxBroken: Int = 9 override val sound: String = "horizonsend:starship.weapon.mining_laser.t3_loop" override val tier: Int = 3 + + override val description: Component = text("Emits a beam $range blocks long that breaks blocks in a $mineRadius block radius.") } object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, +2) @@ -270,6 +276,7 @@ object MiningLaserMultiblockTier3Top : MiningLaserMultiblockTier3() { } object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top) (Mirrored)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, -3) @@ -513,6 +520,7 @@ object MiningLaserMultiblockTier3TopMirrored : MiningLaserMultiblockTier3() { } object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, +2) @@ -756,6 +764,7 @@ object MiningLaserMultiblockTier3Bottom : MiningLaserMultiblockTier3() { } object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom) (Mirrored)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, -3) @@ -999,6 +1008,7 @@ object MiningLaserMultiblockTier3BottomMirrored : MiningLaserMultiblockTier3() { } object MiningLaserMultiblockTier3Side : MiningLaserMultiblockTier3() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(-1, +1, +8) @@ -1240,6 +1250,7 @@ object MiningLaserMultiblockTier3Side : MiningLaserMultiblockTier3() { } object MiningLaserMultiblockTier3SideMirrored : MiningLaserMultiblockTier3() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side) (Mirrored)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+1, -1, -8) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt index 29d9113265..3bc4ad20f2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/mininglasers/MiningLaserMultiblockTier4.kt @@ -1,31 +1,37 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.mininglasers +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace sealed class MiningLaserMultiblockTier4 : MiningLaserMultiblock() { + val tierText = text("Tier 4").color(NamedTextColor.AQUA) override val signText: Array = arrayOf( - Component.text("Mining ").color(NamedTextColor.DARK_GRAY) - .append(Component.text("Laser").color(NamedTextColor.GREEN)), - Component.text("Tier 4").color(NamedTextColor.AQUA), - Component.text(""), - Component.text("") + text("Mining ").color(NamedTextColor.DARK_GRAY) + .append(text("Laser").color(NamedTextColor.GREEN)), + tierText, + text(""), + text("") ) override val maxPower: Int = 650000 override val beamOrigin = Triple(0, 3, 1) - override val range: Double = 245.0 - override val mineRadius = 11 + final override val range: Double = 245.0 + final override val mineRadius = 11 override val beamCount: Int = 10 override val maxBroken: Int = 11 override val sound: String = "horizonsend:starship.weapon.mining_laser.t4_loop" override val tier: Int = 4 + + override val description: Component = text("Emits a beam $range blocks long that breaks blocks in a $mineRadius block radius.") } object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, +2) @@ -269,6 +275,7 @@ object MiningLaserMultiblockTier4Top : MiningLaserMultiblockTier4() { } object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Top) (Mirrored)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+0, +6, -3) @@ -512,6 +519,7 @@ object MiningLaserMultiblockTier4TopMirrored : MiningLaserMultiblockTier4() { } object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, +2) @@ -755,6 +763,7 @@ object MiningLaserMultiblockTier4Bottom : MiningLaserMultiblockTier4() { } object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Bottom) (Mirrored)")) override val side = BlockFace.DOWN override fun getFirePointOffset(): Vec3i = Vec3i(+0, -6, -3) @@ -998,6 +1007,7 @@ object MiningLaserMultiblockTier4BottomMirrored : MiningLaserMultiblockTier4() { } object MiningLaserMultiblockTier4Side : MiningLaserMultiblockTier4() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(-1, +1, +8) @@ -1238,6 +1248,7 @@ object MiningLaserMultiblockTier4Side : MiningLaserMultiblockTier4() { } object MiningLaserMultiblockTier4SideMirrored : MiningLaserMultiblockTier4() { + override val displayName: Component get() = ofChildren(tierText, text(" Mining Laser (Side) (Mirrored)")) override val side = BlockFace.UP override fun getFirePointOffset(): Vec3i = Vec3i(+1, -1, -8) From 5cc53c6f7de4a52fc053097cc92aace1dfd09a5d Mon Sep 17 00:00:00 2001 From: kwazedilla Date: Fri, 31 Jan 2025 16:37:51 -0800 Subject: [PATCH 462/500] WIP: Finish the rest of the multiblock descriptions --- .../type/defense/passive/areashield/AreaShield.kt | 13 +++++++------ .../dockingtube/ConnectedDockingTubeMultiblock.kt | 4 ++++ .../DisconnectedDockingTubeMultiblock.kt | 4 ++++ .../type/dockingtube/DockingTubeMultiblock.kt | 6 +++++- .../multiblock/type/misc/AirlockMultiblock.kt | 7 ++++++- .../multiblock/type/misc/DecomposerMultiblock.kt | 7 ++++++- .../multiblock/type/misc/ExpandableAirlock.kt | 8 +++++++- .../multiblock/type/misc/FuelTankMultiblock.kt | 8 +++++++- .../multiblock/type/misc/ItemSplitterMultiblock.kt | 6 +++++- .../multiblock/type/misc/MagazineMultiblock.kt | 9 ++++++++- .../features/multiblock/type/misc/MobDefender.kt | 6 ++---- .../multiblock/type/misc/ShipFactoryMultiblock.kt | 8 +++++++- .../multiblock/type/misc/TractorBeamMultiblock.kt | 11 ++++++++++- .../type/particleshield/BoxShieldMultiblock.kt | 8 +++++++- .../type/particleshield/ShieldMultiblockClass08.kt | 10 +++++++++- .../type/particleshield/ShieldMultiblockClass08i.kt | 8 ++++++++ .../type/particleshield/ShieldMultiblockClass20.kt | 9 ++++++++- .../type/particleshield/ShieldMultiblockClass30.kt | 10 +++++++++- .../type/particleshield/ShieldMultiblockClass65.kt | 10 +++++++++- .../type/particleshield/ShieldMultiblockClass85.kt | 8 ++++++++ .../type/particleshield/SphereShieldMultiblock.kt | 3 ++- .../type/starship/LandingGearMultiblock.kt | 7 ++++++- .../multiblock/type/starship/OdometerMultiblock.kt | 6 +++++- .../type/starship/checklist/AbstractReactorCore.kt | 3 ++- .../starship/checklist/BargeReactorMultiBlock.kt | 5 +++++ .../checklist/BattleCruiserReactorMultiblock.kt | 5 +++++ .../starship/checklist/CruiserReactorMultiblock.kt | 5 +++++ .../gravitywell/AmplifiedGravityWellMultiblock.kt | 5 +++++ .../starship/gravitywell/GravityWellMultiblock.kt | 3 ++- .../gravitywell/StandardGravityWellMultiblock.kt | 5 +++++ .../starship/hyperdrive/HyperdriveMultiblock.kt | 6 +++++- .../hyperdrive/HyperdriveMultiblockClass1.kt | 4 ++++ .../hyperdrive/HyperdriveMultiblockClass2.kt | 4 ++++ .../hyperdrive/HyperdriveMultiblockClass3.kt | 4 ++++ .../hyperdrive/HyperdriveMultiblockClass4.kt | 4 ++++ .../NavigationComputerMultiblock.kt | 3 ++- .../NavigationComputerMultiblockAdvanced.kt | 7 ++++--- .../NavigationComputerMultiblockBasic.kt | 5 +++++ .../heavy/ArsenalRocketStarshipWeaponMultiblock.kt | 8 +++++++- .../heavy/HeavyLaserStarshipWeaponMultiblock.kt | 2 +- .../weapon/heavy/PhaserStarshipWeaponMultiblock.kt | 9 ++++++++- .../misc/PointDefenseStarshipWeaponMultiblock.kt | 8 ++++---- .../starship/weapon/turret/CycleTurretMultiblock.kt | 5 +++++ .../starship/weapon/turret/HeavyTurretMultiblock.kt | 5 +++++ .../starship/weapon/turret/IonTurretMultiblock.kt | 5 +++++ .../starship/weapon/turret/LightTurretMultiblock.kt | 5 +++++ .../weapon/turret/LogisticTurretMultiblock.kt | 5 +++++ .../starship/weapon/turret/QuadTurretMultiblock.kt | 4 ++++ .../starship/weapon/turret/TriTurretMultiblock.kt | 4 ++++ .../type/starship/weapon/turret/TurretMultiblock.kt | 7 ------- 50 files changed, 263 insertions(+), 48 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt index c9a1f847ea..03e29a2881 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/defense/passive/areashield/AreaShield.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.defense.passive.areashield import net.horizonsend.ion.common.extensions.success +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.multiblock.Multiblock @@ -31,11 +33,6 @@ abstract class AreaShield(val radius: Int) : Multiblock(), EntityMultiblock = getSphereBlocks(radius) @@ -68,14 +65,18 @@ abstract class AreaShield(val radius: Int) : Multiblock(), EntityMultiblock, InteractableMultiblock { +object DecomposerMultiblock : Multiblock(), EntityMultiblock, InteractableMultiblock, DisplayNameMultilblock { override val name: String = "decomposer" override val signText = createSignText( "&cDecomposer", @@ -43,6 +45,9 @@ object DecomposerMultiblock : Multiblock(), EntityMultiblock { +object ItemSplitterMultiblock : Multiblock(), InteractableMultiblock, EntityMultiblock, DisplayNameMultilblock { override val name: String = "splitter" private fun formatText(text: String, vararg params: String) = template(text(text, AQUA), paramColor = YELLOW, useQuotesAroundObjects = false, *params) @@ -46,6 +47,9 @@ object ItemSplitterMultiblock : Multiblock(), InteractableMultiblock, EntityMult RIGHT ) + override val displayName: Component get() = text("Item Splitter") + override val description: Component get() = text("Sorts items based on a whitelist/blacklist system.") + override fun MultiblockShape.buildStructure() { z(+0) { y(+1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt index e763219ab4..df8148fd5e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MagazineMultiblock.kt @@ -2,9 +2,12 @@ package net.horizonsend.ion.server.features.multiblock.type.misc import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material -abstract class AbstractMagazineMultiblock : Multiblock() { +abstract class AbstractMagazineMultiblock : Multiblock(), DisplayNameMultilblock { override val name: String = "magazine" override val signText = createSignText( "&7-=[&c=&a=&b=&7]=-", @@ -13,9 +16,12 @@ abstract class AbstractMagazineMultiblock : Multiblock() { "&7-=[&c=&a=&b=&7]=-" ) abstract val mirrored: Boolean + + override val description: Component get() = text("Stores ammunition for starship weapons.") } object MagazineMultiblock : AbstractMagazineMultiblock() { + override val displayName: Component get() = text("Magazine") override val mirrored = false override fun MultiblockShape.buildStructure() { y(+0) { @@ -32,6 +38,7 @@ object MagazineMultiblock : AbstractMagazineMultiblock() { } object MagazineMultiblockMirrored : AbstractMagazineMultiblock() { + override val displayName: Component get() = text("Magazine (Mirrored)") override val mirrored = true override fun MultiblockShape.buildStructure() { y(+0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt index 939f71fa37..0b8159a8a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/MobDefender.kt @@ -29,10 +29,8 @@ object MobDefender : Multiblock(), EntityMultiblock): Boolean { val modified = lines.toMutableList() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt index 472624623e..e1e4312ebd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass30.kt @@ -1,16 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object ShieldMultiblockClass30 : SphereShieldMultiblock() { override val maxRange = 22 + const val SHIELD_CLASS_TEXT = "&8Class &b3.0" override val signText = createSignText( line1 = "&3Particle Shield", line2 = "&7Generator", line3 = null, - line4 = "&8Class &b3.0" + line4 = SHIELD_CLASS_TEXT ) + override val displayName: Component get() = ofChildren(legacyAmpersand.deserialize(SHIELD_CLASS_TEXT), text(" Shield")) + override val description: Component get() = text("Protects a starship from explosion damage within a $maxRange block radius.") + override fun MultiblockShape.buildStructure() { z(-1) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt index d1c3890b54..adf319d687 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass65.kt @@ -1,16 +1,24 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object ShieldMultiblockClass65 : SphereShieldMultiblock() { override val maxRange = 30 + const val SHIELD_CLASS_TEXT = "&8Class &b6.5" override val signText = createSignText( line1 = "&3Particle Shield", line2 = "&7Generator", line3 = null, - line4 = "&8Class &b6.5" + line4 = SHIELD_CLASS_TEXT ) + override val displayName: Component get() = ofChildren(legacyAmpersand.deserialize(SHIELD_CLASS_TEXT), text(" Shield")) + override val description: Component get() = text("Protects a starship from explosion damage within a $maxRange block radius.") + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt index f5756b220b..0b8909b7da 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/ShieldMultiblockClass85.kt @@ -1,9 +1,14 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield +import net.horizonsend.ion.common.utils.text.legacyAmpersand +import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object ShieldMultiblockClass85 : SphereShieldMultiblock() { override val maxRange = 35 + const val SHIELD_CLASS_TEXT = "&8Class &b8.5" override val signText = createSignText( line1 = "&3Particle Shield", line2 = "&7Generator", @@ -11,6 +16,9 @@ object ShieldMultiblockClass85 : SphereShieldMultiblock() { line4 = "&8Class &b8.5" ) + override val displayName: Component get() = ofChildren(legacyAmpersand.deserialize(SHIELD_CLASS_TEXT), text(" Shield")) + override val description: Component get() = text("Protects a starship from explosion damage within a $maxRange block radius.") + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt index 169c9b8dbc..d2a6d41963 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/particleshield/SphereShieldMultiblock.kt @@ -1,10 +1,11 @@ package net.horizonsend.ion.server.features.multiblock.type.particleshield +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getSphereBlocks import org.bukkit.block.Sign -abstract class SphereShieldMultiblock : ShieldMultiblock() { +abstract class SphereShieldMultiblock : ShieldMultiblock(), DisplayNameMultilblock { abstract val maxRange: Int override fun getShieldBlocks(sign: Sign): List = getSphereBlocks(maxRange) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt index 548bdd9ef3..190c58f520 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/LandingGearMultiblock.kt @@ -2,15 +2,20 @@ package net.horizonsend.ion.server.features.multiblock.type.starship import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.LandingGearSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.block.BlockFace import org.bukkit.block.Sign -object LandingGearMultiblock : Multiblock(), SubsystemMultiblock { +object LandingGearMultiblock : Multiblock(), SubsystemMultiblock, DisplayNameMultilblock { + override val displayName: Component get() = text("Landing Gear") + override val description: Component get() = text("Automatically extends and retracts when a starship is turned on or off.") + override val signText = arrayOf(null, null, null, null) override val name: String = javaClass.simpleName diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt index 6f9fd81f7b..a125d96733 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/OdometerMultiblock.kt @@ -4,6 +4,7 @@ import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.common.utils.miscellaneous.roundToHundredth import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.misc.OdometerSubsystem @@ -18,7 +19,10 @@ import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.persistence.PersistentDataType -object OdometerMultiblock : Multiblock(), SubsystemMultiblock, InteractableMultiblock { +object OdometerMultiblock : Multiblock(), SubsystemMultiblock, InteractableMultiblock, DisplayNameMultilblock { + override val displayName: Component get() = text("Odometer") + override val description: Component get() = text("Measures the blocks traveled on a starship.") + override val name: String = "odometer" override val signText: Array = arrayOf( text("Ship Odometer", AQUA), diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/AbstractReactorCore.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/AbstractReactorCore.kt index efb97f2e12..4df785f202 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/AbstractReactorCore.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/AbstractReactorCore.kt @@ -3,10 +3,11 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import org.bukkit.block.Sign import org.bukkit.block.sign.Side -abstract class AbstractReactorCore(val core: MultiblockShape.RequirementBuilder.() -> Unit) : Multiblock() { +abstract class AbstractReactorCore(val core: MultiblockShape.RequirementBuilder.() -> Unit) : Multiblock(), DisplayNameMultilblock { override fun matchesUndetectedSign(sign: Sign): Boolean { return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[reactor]", ignoreCase = true) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt index 3e883097c4..0bb54aee1c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BargeReactorMultiBlock.kt @@ -1,8 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BARGE_REACTOR_CORE +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object BargeReactorMultiBlock : AbstractReactorCore({ customBlock(BARGE_REACTOR_CORE) }) { + override val displayName: Component get() = text("Barge Reactor") + override val description: Component get() = text("Reactor core critical to a Barge's functionality.") + override val name: String = "bargereactor" override val signText = createSignText( "&7-=[&c==&a==&b==&7]=-", diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt index 14d2b90115..ec3fc88f93 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/BattleCruiserReactorMultiblock.kt @@ -1,8 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.BATTLECRUISER_REACTOR_CORE +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object BattleCruiserReactorMultiblock : AbstractReactorCore({ customBlock(BATTLECRUISER_REACTOR_CORE) }) { + override val displayName: Component get() = text("Battlecruiser Reactor") + override val description: Component get() = text("Reactor core critical to a Battlecruiser's functionality.") + override val name: String = "bcreactor" override val signText = createSignText( "&7-=[&c==&a==&b==&7]=-", diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt index f4d4a80c10..f1bf48f670 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/checklist/CruiserReactorMultiblock.kt @@ -1,8 +1,13 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.checklist import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.CRUISER_REACTOR_CORE +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object CruiserReactorMultiblock : AbstractReactorCore({ customBlock(CRUISER_REACTOR_CORE) }) { + override val displayName: Component get() = text("Cruiser Reactor") + override val description: Component get() = text("Reactor core critical to a Cruiser's functionality.") + override val name: String = "cruiserreactor" override val signText = createSignText( diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt index ff6871d221..09fa215323 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/AmplifiedGravityWellMultiblock.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material object AmplifiedGravityWellMultiblock : GravityWellMultiblock() { @@ -12,6 +14,9 @@ object AmplifiedGravityWellMultiblock : GravityWellMultiblock() { line4 = "&8&o[&d&lAmplified&8&o]" ) + override val displayName: Component get() = text("Amplified Gravity Well") + override val description: Component get() = text("Generates a spherical region around the starship that inhibits hyperspace travel.") + override fun MultiblockShape.buildStructure() { z(+0) { y(-1) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt index 930915bff1..017b32ba55 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/GravityWellMultiblock.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell import net.horizonsend.ion.common.extensions.userError import net.horizonsend.ion.common.utils.text.plainText import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.features.starship.Interdiction import net.horizonsend.ion.server.features.starship.active.ActiveStarships @@ -18,7 +19,7 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder -abstract class GravityWellMultiblock : Multiblock(), InteractableMultiblock { +abstract class GravityWellMultiblock : Multiblock(), InteractableMultiblock, DisplayNameMultilblock { override fun matchesUndetectedSign(sign: Sign): Boolean { return super.matchesUndetectedSign(sign) || sign.getSide(Side.FRONT).line(0).plainText().equals("[gravwell]", ignoreCase = true) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt index 34d033de96..b6c34ac4e8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/gravitywell/StandardGravityWellMultiblock.kt @@ -1,10 +1,15 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.gravitywell import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object StandardGravityWellMultiblock : GravityWellMultiblock() { override val name = "gravitywell" + override val displayName: Component get() = text("Gravity Well") + override val description: Component get() = text("Generates a spherical region around the starship that inhibits hyperspace travel.") + override val signText = createSignText( line1 = "&2Gravity", line2 = "&8Generator", diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt index 50d0704dd8..17dc373606 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblock.kt @@ -3,12 +3,14 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.gui.custom.navigation.NavigationSystemMapGui import net.horizonsend.ion.server.features.multiblock.Multiblock import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock import net.horizonsend.ion.server.miscellaneous.utils.CARDINAL_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.add import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.rightFace +import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.BlockFace @@ -18,12 +20,14 @@ import org.bukkit.block.sign.Side import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent -abstract class HyperdriveMultiblock : Multiblock(), InteractableMultiblock { +abstract class HyperdriveMultiblock : Multiblock(), InteractableMultiblock, DisplayNameMultilblock { override val name = "hyperdrive" abstract val maxPower: Int abstract val hyperdriveClass: Int + override val description: Component get() = text("Allows a starship to enter and exit hyperspace. Consumes chetherite.") + protected abstract fun buildHopperOffsets(): List private val hopperOffsets: Map> = diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt index 35b2208636..d74b2667a8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass1.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object HyperdriveMultiblockClass1 : HyperdriveMultiblock() { override val maxPower = 30_000 @@ -13,6 +15,8 @@ object HyperdriveMultiblockClass1 : HyperdriveMultiblock() { line4 = null ) + override val displayName: Component get() = text("Class 1 Hyperdrive") + override val hyperdriveClass = 1 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt index 7d882124cc..18d70457a9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass2.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object HyperdriveMultiblockClass2 : HyperdriveMultiblock() { override val maxPower = 50_000 @@ -13,6 +15,8 @@ object HyperdriveMultiblockClass2 : HyperdriveMultiblock() { line4 = null ) + override val displayName: Component get() = text("Class 2 Hyperdrive") + override val hyperdriveClass = 2 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt index f8220c7f85..381e63cf20 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass3.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object HyperdriveMultiblockClass3 : HyperdriveMultiblock() { override val maxPower = 75_000 @@ -13,6 +15,8 @@ object HyperdriveMultiblockClass3 : HyperdriveMultiblock() { line4 = null ) + override val displayName: Component get() = text("Class 3 Hyperdrive") + override val hyperdriveClass = 3 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt index 75ed495ef5..9a7837f5b8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/hyperdrive/HyperdriveMultiblockClass4.kt @@ -2,6 +2,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.hyperdrive import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object HyperdriveMultiblockClass4 : HyperdriveMultiblock() { override val signText = createSignText( @@ -13,6 +15,8 @@ object HyperdriveMultiblockClass4 : HyperdriveMultiblock() { override val maxPower = 100_000 + override val displayName: Component get() = text("Class 4 Hyperdrive") + override val hyperdriveClass = 4 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt index 451da4c846..599080f8ec 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblock.kt @@ -1,13 +1,14 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.block.Sign import org.bukkit.block.sign.Side import org.bukkit.entity.Player -abstract class NavigationComputerMultiblock : Multiblock() { +abstract class NavigationComputerMultiblock : Multiblock(), DisplayNameMultilblock { override val name = "navcomputer" override fun onTransformSign(player: Player, sign: Sign) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt index 5608695a42..61edf04fe2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt @@ -7,12 +7,13 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.F import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.LEFT import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.RIGHT import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.data.Bisected.Half.BOTTOM import org.bukkit.block.data.Bisected.Half.TOP import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT sealed class NavigationComputerMultiblockAdvanced : NavigationComputerMultiblock(), DisplayNameMultilblock { - override val description: Component = Component.text("Allows jumping without a hyperspace gate") + override val description: Component get() = text("Allows a starship to jump to set coordinates in space. Base range ${NavigationComputerMultiblockBasic.baseRange}.") override val signText = createSignText( line1 = "&6Advanced", line2 = "&8Navigation", @@ -24,7 +25,7 @@ sealed class NavigationComputerMultiblockAdvanced : NavigationComputerMultiblock } data object VerticalNavigationComputerMultiblockAdvanced : NavigationComputerMultiblockAdvanced() { - override val displayName: Component = Component.text("Horizontal Navigation Computer") + override val displayName: Component = text("Advanced Navigation Computer (Horizontal)") override fun MultiblockShape.buildStructure() { z(+0) { @@ -80,7 +81,7 @@ data object VerticalNavigationComputerMultiblockAdvanced : NavigationComputerMul } data object HorizontalNavigationComputerMultiblockAdvanced : NavigationComputerMultiblockAdvanced() { - override val displayName: Component = Component.text("Vertical Navigation Computer") + override val displayName: Component = text("Advanced Navigation Computer (Vertical)") override fun MultiblockShape.buildStructure() { z(0) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt index b06bd4738d..61c1df2a17 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockBasic.kt @@ -1,6 +1,8 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.navigationcomputer import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text object NavigationComputerMultiblockBasic : NavigationComputerMultiblock() { override val signText = createSignText( @@ -10,6 +12,9 @@ object NavigationComputerMultiblockBasic : NavigationComputerMultiblock() { line4 = null ) + override val displayName: Component get() = text("Basic Navigation Computer") + override val description: Component get() = text("Allows a starship to jump to set coordinates in space. Base range $baseRange.") + override val baseRange: Int = 15000 override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt index e889ed30d3..e7438bcf14 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/ArsenalRocketStarshipWeaponMultiblock.kt @@ -1,13 +1,16 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.ArsenalRocketStarshipWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.block.BlockFace -sealed class ArsenalRocketStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +sealed class ArsenalRocketStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { override fun createSubsystem( starship: ActiveStarship, pos: Vec3i, @@ -20,6 +23,9 @@ sealed class ArsenalRocketStarshipWeaponMultiblock : SignlessStarshipWeaponMulti } sealed class VerticalArsenalStarshipWeaponMultiblock : ArsenalRocketStarshipWeaponMultiblock() { + override val displayName: Component get() = text("Arsenal Missile Launcher (${if (getYFactor() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Launches missiles that deal enormous damage only to Area Shields and other land-based defenses. Consumes ammo.") + protected abstract fun getYFactor(): Int override fun MultiblockShape.buildStructure() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt index 47816ed8d7..f4ea02662e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/HeavyLaserStarshipWeaponMultiblock.kt @@ -18,7 +18,7 @@ object HeavyLaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt index 1bcad3d546..cc38d34240 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/heavy/PhaserStarshipWeaponMultiblock.kt @@ -1,14 +1,21 @@ package net.horizonsend.ion.server.features.multiblock.type.starship.weapon.heavy import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock import net.horizonsend.ion.server.features.multiblock.type.starship.weapon.SignlessStarshipWeaponMultiblock import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.PhaserWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material import org.bukkit.block.BlockFace -object PhaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock() { +object PhaserStarshipWeaponMultiblock : SignlessStarshipWeaponMultiblock(), DisplayNameMultilblock { + + override val displayName: Component get() = text("Phaser") + override val description: Component get() = text("Deals heavy shield damage after a warm-up period. Consumes ammo.") + override fun MultiblockShape.buildStructure() { y(+0) { z(+0..+4 step 2) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt index f295abaf63..e21c52fb07 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/misc/PointDefenseStarshipWeaponMultiblock.kt @@ -16,16 +16,14 @@ sealed class PointDefenseStarshipWeaponMultiblock : SignlessStarshipWeaponMultib return PointDefenseSubsystem(starship, pos, adjustedFace) } - override val displayName: Component - get() = text("Point Defense Turret") - override val description: Component - get() = text("An automatic-only weapon effective against players and entities.") + override val description: Component get() = text("Automated weapon system effective against players and entities. Cannot be manually controlled.") protected abstract fun getAdjustedFace(originalFace: BlockFace): BlockFace } object PointDefenseStarshipWeaponMultiblockTop : PointDefenseStarshipWeaponMultiblock() { override fun getAdjustedFace(originalFace: BlockFace): BlockFace = BlockFace.UP + override val displayName: Component get() = text("Point Defense Turret (Top)") override fun MultiblockShape.buildStructure() { at(+0, +0, +0).dispenser() @@ -36,6 +34,7 @@ object PointDefenseStarshipWeaponMultiblockTop : PointDefenseStarshipWeaponMulti object PointDefenseStarshipWeaponMultiblockBottom : PointDefenseStarshipWeaponMultiblock() { override fun getAdjustedFace(originalFace: BlockFace): BlockFace = BlockFace.DOWN + override val displayName: Component get() = text("Point Defense Turret (Bottom)") override fun MultiblockShape.buildStructure() { at(+0, +0, +0).dispenser() @@ -46,6 +45,7 @@ object PointDefenseStarshipWeaponMultiblockBottom : PointDefenseStarshipWeaponMu object PointDefenseStarshipWeaponMultiblockSide : PointDefenseStarshipWeaponMultiblock() { override fun getAdjustedFace(originalFace: BlockFace): BlockFace = originalFace + override val displayName: Component get() = text("Point Defense Turret (Side)") override fun MultiblockShape.buildStructure() { at(+0, +0, +0).dispenser() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt index d664c9f337..90b03c63c4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/CycleTurretMultiblock.kt @@ -9,6 +9,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.CycleTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.CycleTurretProjectile import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.World import org.bukkit.block.BlockFace import org.bukkit.util.Vector @@ -17,6 +19,9 @@ sealed class CycleTurretMultiblock : TurretMultiblock() { val slowedStarships = mutableMapOf() + override val displayName: Component get() = text("Cycle Turret (${if (getYFactor() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system effective against small targets. Rapid fire and slows ships down.") + override fun createSubsystem(starship: ActiveStarship, pos: Vec3i, face: BlockFace): TurretWeaponSubsystem { return CycleTurretWeaponSubsystem(starship, pos, getFacing(pos, starship), this) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt index 92ef575bed..34e860c552 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/HeavyTurretMultiblock.kt @@ -6,6 +6,8 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.HeavyTurretWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR import org.bukkit.block.BlockFace @@ -15,6 +17,9 @@ sealed class HeavyTurretMultiblock : TurretMultiblock() { return HeavyTurretWeaponSubsystem(starship, pos, getFacing(pos, starship), this) } + override val displayName: Component get() = text("Heavy Turret (${if (getSign() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system effective against medium and large targets. Manual fire only.") + protected abstract fun getSign(): Int override fun getBalancing(starship: ActiveStarship): StarshipWeapons.StarshipWeapon = starship.balancing.weapons.heavyTurret diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt index 780397ad89..7c3ea7362e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/IonTurretMultiblock.kt @@ -8,6 +8,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.IonTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.IonTurretProjectile import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material.END_ROD import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR @@ -22,6 +24,9 @@ sealed class IonTurretMultiblock : TurretMultiblock() { protected abstract fun getSign(): Int + override val displayName: Component get() = text("Ion Turret (${if (getSign() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system that slows down starships that are cruising and in Direct Control mode. Manual fire only. Consumes ammo.") + override fun getBalancing(starship: ActiveStarship): StarshipWeapons.StarshipWeapon = starship.balancing.weapons.ionTurret override fun buildFirePointOffsets(): List = diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt index 6dd6f0bc31..6239e1c8fe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LightTurretMultiblock.kt @@ -6,6 +6,8 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LightTurretWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material.GRINDSTONE import org.bukkit.block.BlockFace @@ -14,6 +16,9 @@ sealed class LightTurretMultiblock : TurretMultiblock() { return LightTurretWeaponSubsystem(starship, pos, getFacing(pos, starship), this) } + override val displayName: Component get() = text("Light Turret (${if (getSign() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system effective against small targets. Can be auto-targeting.") + protected abstract fun getSign(): Int override fun getBalancing(starship: ActiveStarship): StarshipWeapons.StarshipWeapon = starship.balancing.weapons.lightTurret diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt index 94a70d9e0c..88c83d673e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/LogisticTurretMultiblock.kt @@ -8,6 +8,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.LogisticTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.LogisticTurretProjectile import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material.GRINDSTONE import org.bukkit.World import org.bukkit.block.BlockFace @@ -19,6 +21,9 @@ sealed class LogisticTurretMultiblock : TurretMultiblock() { return LogisticTurretWeaponSubsystem(starship, pos, getFacing(pos, starship), this) } + override val displayName: Component get() = text("Cycle Turret (${if (getSign() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system that heals other starships.") + protected abstract fun getSign(): Int override fun getBalancing(starship: ActiveStarship): StarshipWeapons.StarshipWeapon = starship.balancing.weapons.logisticTurret diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt index 165620ef20..99ae7bf45c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/QuadTurretMultiblock.kt @@ -8,6 +8,8 @@ import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeapo import net.horizonsend.ion.server.features.starship.subsystem.weapon.primary.QuadTurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.projectile.QuadTurretProjectile import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR import org.bukkit.World @@ -23,6 +25,8 @@ sealed class QuadTurretMultiblock : TurretMultiblock() { protected abstract fun getSign(): Int + override val displayName: Component get() = text("Quad Turret (${if (getSign() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system effective against the largest targets. Manual fire only. Consumes ammo.") override fun getBalancing(starship: ActiveStarship): StarshipWeapons.StarshipWeapon = starship.balancing.weapons.quadTurret diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt index 8eb4e22497..a042942b0a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TriTurretMultiblock.kt @@ -6,6 +6,8 @@ import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.starship.subsystem.weapon.TurretWeaponSubsystem import net.horizonsend.ion.server.features.starship.subsystem.weapon.secondary.TriTurretWeaponSubsystem import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text import org.bukkit.Material.GRINDSTONE import org.bukkit.Material.IRON_TRAPDOOR import org.bukkit.block.BlockFace @@ -17,6 +19,8 @@ sealed class TriTurretMultiblock : TurretMultiblock() { protected abstract fun getYFactor(): Int + override val displayName: Component get() = text("Tri Turret (${if (getYFactor() == 1) "Top" else "Bottom"})") + override val description: Component get() = text("Rotating weapon system effective against large targets. Can be auto-targeting.") override fun getBalancing(starship: ActiveStarship): StarshipWeapons.StarshipWeapon = starship.balancing.weapons.triTurret diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt index 081d90025b..6c8f8aaa7e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/weapon/turret/TurretMultiblock.kt @@ -18,8 +18,6 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.blockKey import net.horizonsend.ion.server.miscellaneous.utils.leftFace import net.horizonsend.ion.server.miscellaneous.utils.nms import net.horizonsend.ion.server.miscellaneous.utils.rightFace -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.Component.text import net.minecraft.world.level.block.Rotation import org.bukkit.Location import org.bukkit.Material @@ -42,11 +40,6 @@ abstract class TurretMultiblock : Multiblock(), SubsystemMultiblock Date: Sat, 1 Feb 2025 01:06:42 -0800 Subject: [PATCH 463/500] fixed some formatting issues --- .../multiblock/type/farming/harvester/HarvesterMultiblock.kt | 3 ++- .../multiblock/type/farming/planter/PlanterMultiblock.kt | 3 ++- .../navigationcomputer/NavigationComputerMultiblockAdvanced.kt | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt index c20de75531..ccdb617058 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/harvester/HarvesterMultiblock.kt @@ -19,6 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA @@ -44,7 +45,7 @@ abstract class HarvesterMultiblock(val tierMaterial: Material, val tierNumber: I null ) - override val displayName: Component = ofChildren(tierText, nameText) + override val displayName: Component = ofChildren(tierText, space(), nameText) override val description: Component get() = text("Harvests crops. Crops will be harvested opposite of the sign, up to $regionDepth blocks away.") val powerPerCrop: Int = 10 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt index 9aed3f0f1a..cd0d40acc8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/farming/planter/PlanterMultiblock.kt @@ -19,6 +19,7 @@ import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilbloc import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.multiblock.type.farming.Crop import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.space import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor.BLUE import net.kyori.adventure.text.format.NamedTextColor.DARK_AQUA @@ -44,7 +45,7 @@ abstract class PlanterMultiblock(val tierMaterial: Material, val tierNumber: Int null ) - override val displayName: Component = ofChildren(tierText, nameText) + override val displayName: Component = ofChildren(tierText, space(), nameText) override val description: Component get() = text("Plants crops on farmland. Crops will be planted opposite of the sign, up to $regionDepth blocks away.") abstract val regionDepth: Int diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt index 61edf04fe2..13de86692a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/starship/navigationcomputer/NavigationComputerMultiblockAdvanced.kt @@ -13,7 +13,7 @@ import org.bukkit.block.data.Bisected.Half.TOP import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT sealed class NavigationComputerMultiblockAdvanced : NavigationComputerMultiblock(), DisplayNameMultilblock { - override val description: Component get() = text("Allows a starship to jump to set coordinates in space. Base range ${NavigationComputerMultiblockBasic.baseRange}.") + override val description: Component get() = text("Allows a starship to jump to set coordinates in space. Base range $baseRange.") override val signText = createSignText( line1 = "&6Advanced", line2 = "&8Navigation", From dc87cf60c503d0edfaa236f0983fec1464451da9 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Fri, 31 Jan 2025 12:53:27 -0600 Subject: [PATCH 464/500] fix comment --- .../server/features/multiblock/entity/MultiblockEntity.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt index 9cd3c22fee..61e67fa6a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/entity/MultiblockEntity.kt @@ -29,9 +29,9 @@ import org.bukkit.persistence.PersistentDataAdapterContext * @param manager The multiblock manager that this is registered to * @param multiblock The type of multiblock this entity represents * - * @param x The absolute x position of this multiblock's origin location - * @param y The absolute x position of this multiblock's origin location - * @param z The absolute x position of this multiblock's origin location + * @param localOffsetX The local x position of this multiblock's origin location + * @param localOffsetY The local y position of this multiblock's origin location + * @param localOffsetZ The local z position of this multiblock's origin location * @param world The world this multiblock is in * * @param structureDirection The direction this multiblock is oriented [from the origin] From 63c0cbea5d702bd10d2441455726e46cd49733d6 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 1 Feb 2025 11:53:09 -0600 Subject: [PATCH 465/500] Improve world edit integration --- .../features/multiblock/MultiblockEntities.kt | 43 ++++++++++++------- .../features/transport/util/IonChangeSet.kt | 18 +++++--- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index d4c0f938e0..eb3a0ac717 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -1,16 +1,17 @@ package net.horizonsend.ion.server.features.multiblock import com.destroystokyo.paper.event.server.ServerTickEndEvent +import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.LegacyMultiblockEntity import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.world.IonWorld.Companion.ion import net.horizonsend.ion.server.features.world.chunk.IonChunk -import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.MULTIBLOCK_ENTITY_DATA +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getRelative import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY @@ -19,18 +20,22 @@ import net.horizonsend.ion.server.miscellaneous.utils.getFacing import org.bukkit.World import org.bukkit.block.Block import org.bukkit.block.Sign as SignState -import org.bukkit.block.data.type.WallSign as SignData +import org.bukkit.block.data.type.WallSign as WallSignData import org.bukkit.event.EventHandler /** * Provides utility functions for multiblock entities, and handles sign backups **/ -object MultiblockEntities : SLEventListener() { +object MultiblockEntities : IonServerComponent() { + override fun onEnable() { + Tasks.asyncRepeat(20L, 20L, ::performCleaup) + } + /** * **/ fun getMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { - val ionChunk = getIonChunk(world, x, z) ?: return null + val ionChunk = IonChunk.getFromWorldCoordinates(world, x, z) ?: return null return ionChunk.multiblockManager[x, y, z] } @@ -42,7 +47,7 @@ object MultiblockEntities : SLEventListener() { val x = getX(key) val y = getY(key) val z = getZ(key) - val ionChunk = getIonChunk(world, x, z) ?: return null + val ionChunk = IonChunk.getFromWorldCoordinates(world, x, z) ?: return null return ionChunk.multiblockManager[x, y, z] } @@ -56,12 +61,12 @@ object MultiblockEntities : SLEventListener() { return getMultiblockEntity(sign.world, origin.x, origin.y, origin.z) } - fun getMultiblockEntity(signLocation: BlockKey, world: World, sign: SignData): MultiblockEntity? { + fun getMultiblockEntity(signLocation: BlockKey, world: World, sign: WallSignData): MultiblockEntity? { val origin = getRelative(signLocation, sign.facing.oppositeFace) return getMultiblockEntity(world, getX(origin), getY(origin), getZ(origin)) } - fun getMultiblockEntity(signX: Int, signY: Int, signZ: Int, world: World, sign: SignData): MultiblockEntity? { + fun getMultiblockEntity(signX: Int, signY: Int, signZ: Int, world: World, sign: WallSignData): MultiblockEntity? { val structureDirection = sign.facing.oppositeFace return getMultiblockEntity(world, signX + structureDirection.modX, signY + structureDirection.modY, signZ + structureDirection.modZ) } @@ -70,7 +75,7 @@ object MultiblockEntities : SLEventListener() { * Add a new multiblock entity to the chunk **/ fun setMultiblockEntity(world: World, x: Int, y: Int, z: Int, createEntity: (MultiblockManager) -> MultiblockEntity): MultiblockEntity? { - val ionChunk = getIonChunk(world, x, z) ?: return null + val ionChunk = IonChunk.getFromWorldCoordinates(world, x, z) ?: return null val manager = ionChunk.multiblockManager @@ -84,16 +89,19 @@ object MultiblockEntities : SLEventListener() { * **/ fun removeMultiblockEntity(world: World, x: Int, y: Int, z: Int): MultiblockEntity? { - val ionChunk = getIonChunk(world, x, z) ?: return null + val ionChunk = IonChunk.getFromWorldCoordinates(world, x, z) ?: return null return ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) } - private fun getIonChunk(world: World, x: Int, z: Int): IonChunk? { - val chunkX = x.shr(4) - val chunkZ = z.shr(4) + /** + * + **/ + fun removeMultiblockEntity(world: World, signX: Int, signY: Int, signZ: Int, wallSignData: WallSignData): MultiblockEntity? { + val (x, y, z) = Vec3i(signX, signY, signZ).getRelative(wallSignData.facing.oppositeFace) + val ionChunk = IonChunk.getFromWorldCoordinates(world, x, z) ?: return null - return world.ion.getChunk(chunkX, chunkZ) + return ionChunk.multiblockManager.removeMultiblockEntity(x, y, z) } fun loadFromData(multiblock: EntityMultiblock, manager: MultiblockManager, stored: PersistentMultiblockData): T { @@ -124,7 +132,7 @@ object MultiblockEntities : SLEventListener() { fun migrateFromSign(sign: SignState, type: EntityMultiblock<*>) { val origin = MultiblockEntity.getOriginFromSign(sign) - val ionChunk = getIonChunk(sign.world, origin.x, origin.z) ?: return + val ionChunk = IonChunk.getFromWorldCoordinates(sign.world, origin.x, origin.z) ?: return val new = ionChunk.multiblockManager.handleNewMultiblockEntity(type, origin.x, origin.y, origin.z, sign.getFacing().oppositeFace) if (new is LegacyMultiblockEntity) new.loadFromSign(sign) @@ -145,6 +153,11 @@ object MultiblockEntities : SLEventListener() { manager.markSignSaved() } + } + fun performCleaup() { + MultiblockTicking.iterateManagers { + + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt index 521562a8af..5f91ccfd58 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/IonChangeSet.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import org.bukkit.block.Sign +import org.bukkit.block.data.type.WallSign import java.util.Collections class IonChangeSet(world: World) : AbstractChangeSet(world) { @@ -25,10 +26,17 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { addWriteTask { NewTransport.invalidateCache(bukkitWorld, x, y, z) - val type = BukkitAdapter.adapt(BlockTypesCache.states[combinedTo].blockType) + val oldData = BukkitAdapter.adapt(BlockTypesCache.states[combinedFrom]) + val newType = BukkitAdapter.adapt(BlockTypesCache.states[combinedTo].blockType) - if (type.isWallSign) processMultiblock(x, y, z) - if (type.isAir) removeMultiblock(x, y, z) + if (newType.isWallSign) processMultiblock(x, y, z) + if (newType.isAir) { + MultiblockEntities.removeMultiblockEntity(bukkitWorld, x, y, z) + + if (oldData.material.isWallSign) { + MultiblockEntities.removeMultiblockEntity(bukkitWorld, x, y, z, oldData as WallSign) + } + } } } @@ -44,10 +52,6 @@ class IonChangeSet(world: World) : AbstractChangeSet(world) { } } - private fun removeMultiblock(x: Int, y: Int, z: Int) { - MultiblockEntities.removeMultiblockEntity(bukkitWorld, x, y, z) - } - private var recording: Boolean = true override fun isRecordingChanges(): Boolean { From 455c8904be5eba185f8d37b153415bf114c8cfa7 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 1 Feb 2025 12:19:38 -0600 Subject: [PATCH 466/500] Replace command blocks with creaking hearts --- .../extractor/AdvancedItemExtractorBlock.kt | 12 +++++++----- .../custom/blocks/filter/CustomFilterBlock.kt | 6 +++--- .../custom/blocks/filter/ItemFilterBlock.kt | 18 +++++++++--------- .../gui/custom/filter/ItemFilterGui.kt | 8 ++++---- .../transport/filters/manager/FilterManager.kt | 10 +++++----- .../features/transport/util/CacheType.kt | 6 +++--- .../server/listener/fixers/CancelListeners.kt | 7 +++++++ 7 files changed, 38 insertions(+), 29 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 9802e7ea30..54c2693535 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -12,17 +12,19 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block -import org.bukkit.block.BlockFace +import org.bukkit.block.data.type.CreakingHeart import org.bukkit.entity.Player object AdvancedItemExtractorBlock : CustomExtractorBlock( "ADVANCED_ITEM_EXTRACTOR", - blockData = Material.COMMAND_BLOCK.createBlockData { t -> - t as org.bukkit.block.data.type.CommandBlock - t.facing = BlockFace.UP - t.isConditional = false + blockData = Material.CREAKING_HEART.createBlockData { t -> + t as CreakingHeart + t.axis = Axis.X + t.isNatural = false + t.isActive = false }, BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt index 188c2121c3..76f0aec193 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -12,7 +12,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import org.bukkit.block.Block -import org.bukkit.block.CommandBlock +import org.bukkit.block.TileState import org.bukkit.block.data.BlockData import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent @@ -40,7 +40,7 @@ abstract class CustomFilterBlock( cooldown.tryExec(event.player) { Tasks.sync { @Suppress("UNCHECKED_CAST") - val gui = getGui(event.player, block, filterData as FilterData) { block.state as CommandBlock } + val gui = getGui(event.player, block, filterData as FilterData) { block.state as TileState } gui.open() } @@ -49,5 +49,5 @@ abstract class CustomFilterBlock( abstract fun createData(pos: BlockKey): FilterData - abstract fun getGui(player: Player, block: Block, filterData: FilterData, commandBlock: Supplier) : GuiWrapper + abstract fun getGui(player: Player, block: Block, filterData: FilterData, tileState: Supplier) : GuiWrapper } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index 288db06c2b..5666ba67a3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -9,27 +9,27 @@ import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block -import org.bukkit.block.BlockFace -import org.bukkit.block.CommandBlock +import org.bukkit.block.data.type.CreakingHeart import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import java.util.function.Supplier object ItemFilterBlock : CustomFilterBlock( identifier = "ITEM_FILTER", - blockData = Material.COMMAND_BLOCK.createBlockData { t -> - t as org.bukkit.block.data.type.CommandBlock - t.facing = BlockFace.UP - t.isConditional = true + blockData = Material.CREAKING_HEART.createBlockData { t -> + t as CreakingHeart + t.axis = Axis.Z + t.isNatural = false + t.isActive = false }, drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ITEM_FILTER) ), customBlockItem = CustomItemRegistry::ITEM_FILTER, - ) { override fun createData(pos: BlockKey): FilterData { return FilterData(pos, FilterType.ItemType) @@ -39,8 +39,8 @@ object ItemFilterBlock : CustomFilterBlock( player: Player, block: Block, filterData: FilterData, - commandBlock: Supplier + tileState: Supplier ): GuiWrapper { - return ItemFilterGui(player, filterData, commandBlock) + return ItemFilterGui(player, filterData, tileState) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt index 377f4380bd..41b65b4a54 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.filters.manager.FilterManager import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text -import org.bukkit.block.CommandBlock +import org.bukkit.block.TileState import org.bukkit.entity.Player import org.bukkit.event.inventory.ClickType import org.bukkit.event.inventory.InventoryClickEvent @@ -26,7 +26,7 @@ import xyz.xenondevs.invui.item.impl.AbstractItem import xyz.xenondevs.invui.window.Window import java.util.function.Supplier -class ItemFilterGui(val viewer: Player, private val data: FilterData, private val commandBlock: Supplier) : GuiWrapper { +class ItemFilterGui(val viewer: Player, private val data: FilterData, private val tileState: Supplier) : GuiWrapper { private var currentWindow: Window? = null val whitelistText get() = if (data.isWhitelist) text("Whitelist") else text("Blacklist") @@ -99,7 +99,7 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData) { val filters = Long2ObjectOpenHashMap>() @@ -75,7 +75,7 @@ abstract class FilterManager(open val manager: TransportManager<*>) { val global = manager.getGlobalCoordinate(toVec3i(key)) val world = manager.getWorld() - val state = world.getBlockState(global.x, global.y, global.z) as? CommandBlock + val state = world.getBlockState(global.x, global.y, global.z) as? TileState @Suppress("UNCHECKED_CAST") val data = state?.persistentDataContainer?.get(NamespacedKeys.FILTER_DATA, FilterData) as? FilterData ?: block.createData(key) @@ -97,9 +97,9 @@ abstract class FilterManager(open val manager: TransportManager<*>) { abstract fun load() companion object { - fun save(commandBlock: CommandBlock, data: FilterData<*, *>) { - commandBlock.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, data) - commandBlock.update() + fun save(tileState: TileState, data: FilterData<*, *>) { + tileState.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, data) + tileState.update() } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index df9546c675..faa12a17fa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -41,7 +41,7 @@ import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.NamespacedKey -import org.bukkit.block.data.type.CommandBlock +import org.bukkit.block.data.type.CreakingHeart import org.bukkit.block.data.type.Hopper import org.bukkit.block.data.type.Observer import org.bukkit.craftbukkit.block.impl.CraftEndRod @@ -112,14 +112,14 @@ enum class CacheType(val namespacedKey: NamespacedKey) { ITEMS(NamespacedKeys.ITEM_TRANSPORT) { override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) - .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _, _ -> ItemNode.ItemExtractorNode } + .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _, _ -> ItemNode.ItemExtractorNode } .addSimpleNode(STAINED_GLASS_TYPES) { _, material, _ -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(STAINED_GLASS_PANE_TYPES) { _, material, _ -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(TINTED_GLASS, ItemNode.WildcardSolidGlassNode) .addDataHandler(GRINDSTONE) { data, key, _ -> ItemNode.ItemMergeNode } - .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache) } + .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache) } .addDataHandler(Material.HOPPER) { data, key, holder -> ItemNode.HopperFilterNode(key, data.facing, holder.cache as ItemTransportCache) } .addSimpleNode( Material.CHEST, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt index 4e381d90a6..e74945c5d2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox import net.minecraft.world.entity.item.ItemEntity import org.bukkit.Material import org.bukkit.entity.EnderPearl +import org.bukkit.entity.EntityType import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.block.Action @@ -23,6 +24,7 @@ import org.bukkit.event.block.BlockFadeEvent import org.bukkit.event.block.BlockFormEvent import org.bukkit.event.block.BlockPistonExtendEvent import org.bukkit.event.block.BlockPistonRetractEvent +import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityDamageEvent import org.bukkit.event.entity.EntityExplodeEvent import org.bukkit.event.entity.PotionSplashEvent @@ -217,4 +219,9 @@ class CancelListeners : SLEventListener() { ) } } + + @EventHandler + fun onMonsterSpawn(event: CreatureSpawnEvent) { + if (event.entity.type == EntityType.CREAKING) event.isCancelled = true + } } From 56e88d32c885ba0f399adcb0f86cc6fb3f5bc061 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 1 Feb 2025 12:38:18 -0600 Subject: [PATCH 467/500] Fix exception when loading filters --- .../features/transport/filters/manager/FilterManager.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt index ec20f0b3f6..c9ef65d719 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/manager/FilterManager.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.manager.TransportManager +import net.horizonsend.ion.server.features.transport.util.getBlockEntity import net.horizonsend.ion.server.features.transport.util.getPersistentDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey @@ -73,12 +74,11 @@ abstract class FilterManager(open val manager: TransportManager<*>) { fun registerFilter(key: BlockKey, block: CustomFilterBlock): FilterData { val global = manager.getGlobalCoordinate(toVec3i(key)) - val world = manager.getWorld() - val state = world.getBlockState(global.x, global.y, global.z) as? TileState + val pdc = getBlockEntity(global, manager.getWorld())?.persistentDataContainer @Suppress("UNCHECKED_CAST") - val data = state?.persistentDataContainer?.get(NamespacedKeys.FILTER_DATA, FilterData) as? FilterData ?: block.createData(key) + val data = pdc?.get(NamespacedKeys.FILTER_DATA, FilterData) as? FilterData ?: block.createData(key) addFilter(key, data) From d66646f9c893cb50b3ff53168d8dc302598cd6b9 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 1 Feb 2025 12:46:13 -0600 Subject: [PATCH 468/500] Add display names to sorting methods --- .../server/features/transport/items/SortingOrder.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt index 6c3defa992..3d2481feab 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt @@ -4,15 +4,16 @@ import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i +import net.kyori.adventure.text.Component -enum class SortingOrder { - NEAREST_FIRST { +enum class SortingOrder(val displayName: Component) { + NEAREST_FIRST(Component.text("Nearest First")) { override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { val extractorPosition = toVec3i(extractorData.key) return destinations.minBy { key -> extractorPosition.distance(toVec3i(key)) } } }, - ROUND_ROBIN { + ROUND_ROBIN(Component.text("Round Robin")) { override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { val currentIndex = extractorData.roundRobinIndex.toInt() @@ -21,13 +22,13 @@ enum class SortingOrder { return destinations[nextIndex] } }, - FARTHEST_FIRST { + FARTHEST_FIRST(Component.text("Farthest First")) { override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { val extractorPosition = toVec3i(extractorData.key) return destinations.maxBy { key -> extractorPosition.distance(toVec3i(key)) } } }, - RANDOM { + RANDOM(Component.text("Random")) { override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { return destinations.random() } From 25f124724e82b14ac1cbb3953087ab68f3d82228 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sat, 1 Feb 2025 13:35:03 -0600 Subject: [PATCH 469/500] Advanced item extractor gui --- .../extractor/AdvancedItemExtractorBlock.kt | 85 +++++++++++++++---- .../manager/extractors/ExtractorManager.kt | 8 ++ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 54c2693535..eca4334af7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -1,22 +1,26 @@ package net.horizonsend.ion.server.features.custom.blocks.extractor -import net.horizonsend.ion.common.extensions.information -import net.horizonsend.ion.common.extensions.success import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry +import net.horizonsend.ion.server.features.gui.GuiItems +import net.horizonsend.ion.server.features.gui.GuiText +import net.horizonsend.ion.server.features.gui.GuiWrapper +import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI.Companion.setTitle import net.horizonsend.ion.server.features.transport.items.SortingOrder +import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData -import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache -import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.kyori.adventure.text.Component import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block import org.bukkit.block.data.type.CreakingHeart import org.bukkit.entity.Player +import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper +import xyz.xenondevs.invui.gui.Gui +import xyz.xenondevs.invui.item.impl.AbstractItem +import xyz.xenondevs.invui.window.Window object AdvancedItemExtractorBlock : CustomExtractorBlock( "ADVANCED_ITEM_EXTRACTOR", @@ -38,17 +42,68 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( } override fun openGUI(player: Player, block: Block, extractorData: ItemExtractorData) { - val current = extractorData.metaData.sortingOrder - val entires = SortingOrder.entries - player.information("Current: $current") + AdvancedItemExtractorGUI(player, block, extractorData).open() + } + + class AdvancedItemExtractorGUI(val viewer: Player, val block: Block, val extractorData: ItemExtractorData) : GuiWrapper { + override fun open() { + val gui = Gui.normal() + .setStructure( + "u u u u u u u u u", + ". . . . . . . . .", + "d d d d d d d d d" + ) + .addIngredient('u', getTraverseButton(1)) + .addIngredient('d', getTraverseButton(-1)) + + Window + .single() + .setGui(gui) + .setTitle(AdventureComponentWrapper(getSlotOverlay())) + .build(viewer) + .open() + } + + fun getOffset(offset: Int): SortingOrder { + val current = extractorData.metaData.sortingOrder + val entries = SortingOrder.entries + return SortingOrder.entries[Math.floorMod(current.ordinal + offset, entries.size)] + } + + fun getSlotOverlay(): Component = GuiText("Item Filter") + .setSlotOverlay( + "# # # # # # # # #", + "# # # # # # # # #", + "# # # # # # # # #" + ) + .add( + component = getOffset(+1).displayName, + alignment = GuiText.TextAlignment.CENTER, + line = 0 + ) + .add( + component = getOffset(+0).displayName, + alignment = GuiText.TextAlignment.CENTER, + line = 2, + ) + .add( + component = getOffset(-1).displayName, + alignment = GuiText.TextAlignment.CENTER, + line = 4, + ) + .build() + + fun getTraverseButton(offset: Int): AbstractItem = GuiItems.createButton(GuiItems.blankItem) { _, player, event -> + val current = extractorData.metaData.sortingOrder + val entires = SortingOrder.entries + + val newIndex = Math.floorMod(current.ordinal + offset, entires.size) - val new = if (current.ordinal + 1 > entires.lastIndex) 0 else current.ordinal + 1 + extractorData.metaData.sortingOrder = entires[newIndex] - player.success("New: ${SortingOrder.entries[new]}") - extractorData.metaData.sortingOrder = SortingOrder.entries[new] + ExtractorManager.saveExtractor(block.world, block.x, block.y, block.z, extractorData) - val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return - val itemCache = CacheType.ITEMS.get(chunk) as ItemTransportCache - itemCache.handleExtractorTick(toBlockKey(block.x, block.y, block.z), 1.0, extractorData.metaData) + event.view.setTitle(getSlotOverlay()) + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index 1affb9d191..d86e6405c6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -2,11 +2,14 @@ package net.horizonsend.ion.server.features.transport.manager.extractors import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.extractor.CustomExtractorBlock +import net.horizonsend.ion.server.features.transport.manager.extractors.data.AdvancedExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.features.transport.util.getBlockEntity import net.horizonsend.ion.server.features.transport.util.getPersistentDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getX import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getY import net.horizonsend.ion.server.miscellaneous.utils.coordinates.getZ @@ -57,6 +60,11 @@ abstract class ExtractorManager { return null } + + fun saveExtractor(world: World, x: Int, y: Int, z: Int, data: AdvancedExtractorData<*>) { + val entity = getBlockEntity(Vec3i(x, y, z), world) ?: return + entity.persistentDataContainer.set(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer, data.asMetaDataContainer()) + } } open fun onLoad() {} From 5c96c6424cc10c81e67715bc2595ead9fb828846 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 00:32:02 -0600 Subject: [PATCH 470/500] sort round-robin index by distance --- .../ion/server/features/transport/items/SortingOrder.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt index 3d2481feab..a171a0b9b4 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/items/SortingOrder.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.items import com.manya.pdc.base.EnumDataType import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.distanceSquared import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.kyori.adventure.text.Component @@ -17,9 +18,12 @@ enum class SortingOrder(val displayName: Component) { override fun getDestination(extractorData: ItemExtractorMetaData, destinations: List): BlockKey { val currentIndex = extractorData.roundRobinIndex.toInt() + val extractorPosition = toVec3i(extractorData.key) + val distanceIndexed = destinations.sortedBy { key -> distanceSquared(toVec3i(key), extractorPosition) } + val nextIndex = (currentIndex + 1) % destinations.size extractorData.roundRobinIndex = nextIndex.toUShort() - return destinations[nextIndex] + return distanceIndexed[nextIndex] } }, FARTHEST_FIRST(Component.text("Farthest First")) { From 24c6d500da3bcad378c5c6fcd4fc9511a3549fbe Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 00:34:33 -0600 Subject: [PATCH 471/500] make unselected options gray --- .../blocks/extractor/AdvancedItemExtractorBlock.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index eca4334af7..2a72fab222 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -12,6 +12,7 @@ import net.horizonsend.ion.server.features.transport.manager.extractors.Extracto import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component +import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block @@ -70,16 +71,17 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( return SortingOrder.entries[Math.floorMod(current.ordinal + offset, entries.size)] } - fun getSlotOverlay(): Component = GuiText("Item Filter") + fun getSlotOverlay(): Component = GuiText("Item Extractor Configuration") .setSlotOverlay( "# # # # # # # # #", "# # # # # # # # #", "# # # # # # # # #" ) .add( - component = getOffset(+1).displayName, + component = Component.text().color(NamedTextColor.GRAY).append(getOffset(+1).displayName).build(), alignment = GuiText.TextAlignment.CENTER, - line = 0 + line = 0, + verticalShift = -54 ) .add( component = getOffset(+0).displayName, @@ -87,9 +89,10 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( line = 2, ) .add( - component = getOffset(-1).displayName, + component = Component.text().color(NamedTextColor.GRAY).append(getOffset(-1).displayName).build(), alignment = GuiText.TextAlignment.CENTER, line = 4, + verticalShift = +4 ) .build() From 5a3f199b5b65db08ea302d146ab7dc15153e5ea0 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 01:43:33 -0600 Subject: [PATCH 472/500] make creaking heart fly --- .../horizonsend/ion/server/features/starship/FlyableBlocks.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt index 9ebf6f4222..47ee53c3f5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt @@ -44,12 +44,12 @@ import org.bukkit.Material.CHAIN import org.bukkit.Material.CHEST import org.bukkit.Material.CHIPPED_ANVIL import org.bukkit.Material.COAL_BLOCK -import org.bukkit.Material.COMMAND_BLOCK import org.bukkit.Material.COMPARATOR import org.bukkit.Material.COMPOSTER import org.bukkit.Material.COPPER_BLOCK import org.bukkit.Material.COPPER_GRATE import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.Material.CREAKING_HEART import org.bukkit.Material.CREEPER_HEAD import org.bukkit.Material.CREEPER_WALL_HEAD import org.bukkit.Material.DAMAGED_ANVIL @@ -208,7 +208,7 @@ val FLYABLE_BLOCKS: EnumSet = mutableSetOf( EMERALD_BLOCK, COAL_BLOCK, BROWN_MUSHROOM_BLOCK, // custom ores - COMMAND_BLOCK, // custom blocks + CREAKING_HEART, // custom blocks // used for landing gears PISTON, From df7b3f14863dad2b26bf00a30c801a571c12f2b8 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:05:39 -0600 Subject: [PATCH 473/500] menu adjustment --- .../custom/blocks/extractor/AdvancedItemExtractorBlock.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 2a72fab222..bff47b13bd 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -81,7 +81,7 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( component = Component.text().color(NamedTextColor.GRAY).append(getOffset(+1).displayName).build(), alignment = GuiText.TextAlignment.CENTER, line = 0, - verticalShift = -54 + verticalShift = +4 ) .add( component = getOffset(+0).displayName, @@ -92,7 +92,7 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( component = Component.text().color(NamedTextColor.GRAY).append(getOffset(-1).displayName).build(), alignment = GuiText.TextAlignment.CENTER, line = 4, - verticalShift = +4 + verticalShift = -4 ) .build() From 49a79cb07ccc8562f61ce3bf43da39ff08cff937 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:07:44 -0600 Subject: [PATCH 474/500] Redo path cache to allow for different values --- .../command/misc/TransportDebugCommand.kt | 25 ++++ .../nodes/cache/FluidTransportCache.kt | 126 +++++++++--------- .../nodes/cache/ItemTransportCache.kt | 31 ++++- .../nodes/cache/PowerTransportCache.kt | 15 +++ .../transport/nodes/cache/SolarPanelCache.kt | 3 + .../transport/nodes/cache/TransportCache.kt | 74 +--------- .../transport/nodes/cache/path/PathCache.kt | 87 ++++++++++++ .../transport/util/NodePathfinding.kt | 8 +- 8 files changed, 234 insertions(+), 135 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt index 0f83883149..ed3f0e1a27 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/command/misc/TransportDebugCommand.kt @@ -246,4 +246,29 @@ object TransportDebugCommand : SLCommand() { sender.sendMessage("Solar panel average: ${solarTickTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") sender.sendMessage("Solar flood average: ${solarFloodFillTimes.average().takeIf { d -> d.isFinite() }?.roundToInt()} ns") } + + val idealNumbers: LinkedBlockingDeque = LinkedBlockingDeque() + val stepNumbers: LinkedBlockingDeque = LinkedBlockingDeque() + + @Subcommand("metrics astar") + fun getMetricsAstar(sender: Player) { + val averageStepNumber = stepNumbers.average() + val maxStep = stepNumbers.max() + val minStep = stepNumbers.min() + val averageIdealNumber = idealNumbers.average() + val maxIdeal = idealNumbers.max() + val minIdeal = idealNumbers.min() + + sender.sendRichMessage(""" + maxStep: $maxStep + minStep: $minStep + maxIdeal: $maxIdeal + minIdeal: $minIdeal + + averageIdealNumber: $averageIdealNumber + averageStepNumber: $averageStepNumber + + average : ideal ratio: ${averageStepNumber / averageIdealNumber} + """.trimIndent()) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt index d827781093..78c48d8f36 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/FluidTransportCache.kt @@ -7,7 +7,7 @@ import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidStack import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder -import net.horizonsend.ion.server.features.transport.nodes.types.FilterNode +import net.horizonsend.ion.server.features.transport.nodes.cache.path.PathCache import net.horizonsend.ion.server.features.transport.nodes.types.FluidNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode @@ -22,6 +22,8 @@ class FluidTransportCache(holder: CacheHolder): TransportCa override val type: CacheType = CacheType.FLUID override val extractorNodeClass: KClass = FluidNode.FluidExtractorNode::class + override val pathCache: PathCache<*> = PathCache.keyed(this) + override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { NewTransport.runTask { val world = holder.getWorld() val sources = getExtractorSourceEntities(location) { it.isEmpty() } @@ -79,67 +81,67 @@ class FluidTransportCache(holder: CacheHolder): TransportCa val numDestinations = filteredDestinations.size - val paths: Array = Array(numDestinations) { - findPath(source, filteredDestinations[it]) { node, _ -> - (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) != false) - } - } - - var maximumResistance: Double = -1.0 - - // Perform the calc & max find in the same loop - val pathResistance: Array = Array(numDestinations) { - val res = paths[it]?.resistance - if (res != null && maximumResistance < res) maximumResistance = res - - res - } - - // All null, no paths found - if (maximumResistance == -1.0) return amount - - var shareFactorSum = 0.0 - - // Get a parallel array containing the ascending order of resistances - val sortedIndexes = getSorted(pathResistance) - - val shareFactors: Array = Array(numDestinations) { index -> - val resistance = pathResistance[index] ?: return@Array null - val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) - shareFactorSum += fac - - fac - } - - var remainingAmount = amount - - for ((index, destination) in filteredDestinations.withIndex()) { - val shareFactor = shareFactors[index] ?: continue - val inputData = FluidNode.FluidInputNode.getFluidEntities(source.world, destination) - - val share = shareFactor / shareFactorSum - - val idealSend = (amount * share).roundToInt() - val capacity = getRemainingCapacity(fluid, inputData) - val toSend = minOf(idealSend, capacity) - - // Amount of power that didn't fit - val remainder = distributeFluid(inputData, fluid, toSend) - val realTaken = toSend - remainder - - remainingAmount -= realTaken - completeChain(paths[index]?.traversedNodes, realTaken) - - if (remainder == 0) continue - - // Get the proportion of the amount of power that sent compared to the ideal calculations. - val usedShare = realTaken.toDouble() / idealSend.toDouble() - // Use that to get a proportion of the share factor, and remove that from the sum. - val toRemove = shareFactor * usedShare - shareFactorSum -= toRemove - } - - return remainingAmount +// val paths: Array = Array(numDestinations) { +// findPath(source, filteredDestinations[it]) { node, _ -> +// (node is FluidNode) && (@Suppress("UNCHECKED_CAST") (node as? FilterNode)?.canTransfer(fluid) != false) +// } +// } +// +// var maximumResistance: Double = -1.0 +// +// // Perform the calc & max find in the same loop +// val pathResistance: Array = Array(numDestinations) { +// val res = paths[it]?.resistance +// if (res != null && maximumResistance < res) maximumResistance = res +// +// res +// } +// +// // All null, no paths found +// if (maximumResistance == -1.0) return amount +// +// var shareFactorSum = 0.0 +// +// // Get a parallel array containing the ascending order of resistances +// val sortedIndexes = getSorted(pathResistance) +// +// val shareFactors: Array = Array(numDestinations) { index -> +// val resistance = pathResistance[index] ?: return@Array null +// val fac = (numDestinations - sortedIndexes[index]).toDouble() / (resistance / maximumResistance) +// shareFactorSum += fac +// +// fac +// } +// +// var remainingAmount = amount +// +// for ((index, destination) in filteredDestinations.withIndex()) { +// val shareFactor = shareFactors[index] ?: continue +// val inputData = FluidNode.FluidInputNode.getFluidEntities(source.world, destination) +// +// val share = shareFactor / shareFactorSum +// +// val idealSend = (amount * share).roundToInt() +// val capacity = getRemainingCapacity(fluid, inputData) +// val toSend = minOf(idealSend, capacity) +// +// // Amount of power that didn't fit +// val remainder = distributeFluid(inputData, fluid, toSend) +// val realTaken = toSend - remainder +// +// remainingAmount -= realTaken +// completeChain(paths[index]?.traversedNodes, realTaken) +// +// if (remainder == 0) continue +// +// // Get the proportion of the amount of power that sent compared to the ideal calculations. +// val usedShare = realTaken.toDouble() / idealSend.toDouble() +// // Use that to get a proportion of the share factor, and remove that from the sum. +// val toRemove = shareFactor * usedShare +// shareFactorSum -= toRemove +// } + + return amount } private fun getRemainingCapacity(fluid: Fluid, destinations: List): Int { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 3b80fb78c7..6c0cdde25f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -8,10 +8,14 @@ import net.horizonsend.ion.server.features.transport.items.transaction.ItemTrans import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData.ItemExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.path.PathCache import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.calculatePathResistance import net.horizonsend.ion.server.features.transport.util.getBlockEntity +import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.LegacyItemUtils import net.horizonsend.ion.server.miscellaneous.utils.Tasks @@ -31,12 +35,16 @@ import org.bukkit.block.BlockFace import org.bukkit.craftbukkit.inventory.CraftInventory import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest import org.bukkit.inventory.ItemStack +import java.util.Optional +import kotlin.jvm.optionals.getOrNull import kotlin.reflect.KClass class ItemTransportCache(override val holder: CacheHolder): TransportCache(holder) { override val type: CacheType = CacheType.ITEMS override val extractorNodeClass: KClass = ItemNode.ItemExtractorNode::class + override val pathCache: PathCache>> = PathCache.keyed(this) + override fun tickExtractor( location: BlockKey, delta: Double, @@ -119,14 +127,14 @@ class ItemTransportCache(override val holder: CacheHolder): val paths: Array = Array(destinations.size) { findPath( - origin = Node.NodePositionData( + origin = NodePositionData( ItemNode.ItemExtractorNode, holder.getWorld(), originKey, BlockFace.SELF ), destination = destinations[it], - ignoreCache = true // TODO wait for a caching implementation that will allow compound keys for item types + itemStack = singletonItem, ) { node, blockFace -> if (node !is ItemNode.FilterNode) return@findPath true @@ -154,6 +162,8 @@ class ItemTransportCache(override val holder: CacheHolder): if (room == 0) { validDestinations.remove(destination) + if (validDestinations.isEmpty()) return + destination = getDestination(meta, originKey, validDestinations) continue } @@ -263,4 +273,21 @@ class ItemTransportCache(override val holder: CacheHolder): return inventories } + + fun findPath( + origin: NodePositionData, + destination: BlockKey, + itemStack: ItemStack, + pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null + ): PathfindingReport? { + val entry = pathCache.getOrCompute(origin.position, destination) { mutableMapOf() } ?: return null // Should not return null, but handle the possibility + + return entry.getOrPut(itemStack) { + val path = runCatching { getIdealPath(origin, destination, holder.nodeProvider, pathfindingFilter) }.getOrNull() + if (path == null) return@getOrPut Optional.empty() + + val resistance = calculatePathResistance(path) + Optional.of(PathfindingReport(path, resistance)) + }.getOrNull() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt index 06a307ea24..db7f74a765 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/PowerTransportCache.kt @@ -7,11 +7,15 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredM import net.horizonsend.ion.server.features.transport.NewTransport import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.path.PathCache import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.calculatePathResistance +import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.block.BlockFace import kotlin.math.roundToInt @@ -21,6 +25,8 @@ class PowerTransportCache(holder: CacheHolder) : TransportC override val type: CacheType = CacheType.POWER override val extractorNodeClass: KClass = PowerNode.PowerExtractorNode::class + override val pathCache: PathCache = PathCache.standard(this) + override fun tickExtractor(location: BlockKey, delta: Double, metaData: ExtractorMetaData?) { val solarCache = holder.transportManager.solarPanelManager.cache if (solarCache.isSolarPanel(location)) tickSolarPanel(location, delta, solarCache) @@ -218,4 +224,13 @@ class PowerTransportCache(holder: CacheHolder) : TransportC return remainingPower } + + fun findPath(origin: NodePositionData, destination: BlockKey, pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null): PathfindingReport? = + pathCache.getOrCompute(origin.position, destination) { + val path = runCatching { getIdealPath(origin, destination, holder.nodeProvider, pathfindingFilter) }.getOrNull() + if (path == null) return@getOrCompute null + + val resistance = calculatePathResistance(path) + PathfindingReport(path, resistance) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt index 0eb565d8b2..1e78972ed8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/SolarPanelCache.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.transport.nodes.cache import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.path.PathCache import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType @@ -19,6 +20,8 @@ import kotlin.reflect.KClass class SolarPanelCache(holder: CacheHolder) : TransportCache(holder) { override val type: CacheType = CacheType.SOLAR_PANELS + override val pathCache: PathCache<*> = PathCache.standard(this) + override val extractorNodeClass: KClass = PowerNode.PowerExtractorNode::class sealed interface SolarPanelComponent: Node { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 35819fe271..8f7d33723a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -1,20 +1,18 @@ package net.horizonsend.ion.server.features.transport.nodes.cache -import com.google.common.collect.TreeBasedTable import it.unimi.dsi.fastutil.longs.Long2IntRBTreeMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.starship.movement.StarshipMovement import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder +import net.horizonsend.ion.server.features.transport.nodes.cache.path.PathCache import net.horizonsend.ion.server.features.transport.nodes.types.ComplexNode import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.features.transport.util.MAX_PATHFINDS_OVER_BLOCK -import net.horizonsend.ion.server.features.transport.util.calculatePathResistance -import net.horizonsend.ion.server.features.transport.util.getIdealPath import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i @@ -26,12 +24,9 @@ import net.horizonsend.ion.server.miscellaneous.utils.coordinates.isAdjacent import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toVec3i import net.horizonsend.ion.server.miscellaneous.utils.getBlockIfLoaded -import net.horizonsend.ion.server.miscellaneous.utils.set import org.bukkit.block.Block import org.bukkit.block.BlockFace -import java.util.Optional import java.util.concurrent.ConcurrentHashMap -import kotlin.jvm.optionals.getOrNull import kotlin.reflect.KClass abstract class TransportCache(open val holder: CacheHolder<*>) { @@ -44,7 +39,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { /** * A table containing cached paths. The first value is the origin of the path, usually an extractor, and the second is the destination location. **/ - private val pathCache = TreeBasedTable.create>() + abstract val pathCache: PathCache<*> abstract val type: CacheType val nodeFactory: NodeCacheFactory get() = type.nodeCacheFactory @@ -94,7 +89,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { fun invalidate(key: BlockKey) { val removed = (nodeCache.remove(key) as? CacheState.Present)?.node removed?.onInvalidate() ?: return - invalidatePaths(key, removed) + pathCache.invalidatePaths(key, removed) } fun getRawCache() = nodeCache @@ -232,68 +227,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { return destinations } - private val pathCacheLock = Any() - - fun invalidatePaths(pos: BlockKey, node: Node) { - val toRemove = mutableSetOf>() - - // If the pos is an origin or destination, there is no need to perform a flood to find the connected rows / destinations - // If the path cache contains a row at this pos, an origin is present here, and it can be removed - if (pathCache.containsRow(pos)) { - pathCache.rowMap()[pos]?.keys?.forEach { columnKey -> - toRemove.add(pos to columnKey) - } - } - - // If the path cache contains a column at this pos, a destination from an origin within the chunk can be invalidated - if (pathCache.containsColumn(pos)) { - pathCache.columnMap()[pos]?.keys?.forEach { rowKey -> - toRemove.add(rowKey to pos) - } - } - - // Perform a flood fill to find all network destinations, then remove all destination columns - getNetworkDestinations(clazz = extractorNodeClass, originPos = pos, originNode = node) { - // Traverse network backwards - getPreviousNodes(holder.nodeProvider, null) - }.forEach { extractorPos -> - pathCache.rowMap()[extractorPos]?.keys?.forEach { columnKey -> - toRemove.add(extractorPos to columnKey) - } - } - - // Remove all the paths after being found - synchronized(pathCacheLock) { - for ((rowKey, columnKey) in toRemove) pathCache.remove(rowKey, columnKey) - } - } - - fun findPath( - origin: Node.NodePositionData, - destination: BlockKey, - ignoreCache: Boolean = false, - pathfindingFilter: ((Node, BlockFace) -> Boolean)? = null - ): PathfindingReport? { - if (!ignoreCache && pathCache.contains(origin.position, destination)) { - return synchronized(pathCacheLock) { pathCache.get(origin.position, destination)?.getOrNull() } - } - - val path = runCatching { getIdealPath(origin, destination, holder.nodeProvider, pathfindingFilter) }.getOrNull() - - if (path == null) { - if (!ignoreCache) synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.empty() } - return null - } - - val resistance = calculatePathResistance(path) - - val report = PathfindingReport(path, resistance) - - if (!ignoreCache) synchronized(pathCacheLock) { pathCache[origin.position, destination] = Optional.of(report) } - return report - } - - data class PathfindingReport(val traversedNodes: Array, val resistance: Double) { + data class PathfindingReport(val traversedNodes: Array, val resistance: Double) { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt new file mode 100644 index 0000000000..f466cb40f2 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt @@ -0,0 +1,87 @@ +package net.horizonsend.ion.server.features.transport.nodes.cache.path + +import com.google.common.collect.TreeBasedTable +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache +import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache.PathfindingReport +import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.set +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +class PathCache(val cache: TransportCache) { + private val pathCache = TreeBasedTable.create>() + + private val lock = Any() + + fun contains(origin: BlockKey, destination: BlockKey): Boolean { + return synchronized(lock) { + pathCache.contains(origin, destination) + } + } + + fun get(origin: BlockKey, destination: BlockKey): T? { + return synchronized(lock) { + pathCache.get(origin, destination)?.getOrNull() + } + } + + fun set(origin: BlockKey, destination: BlockKey, value: T?) { + synchronized(lock) { + pathCache[origin, destination] = Optional.ofNullable(value) + } + } + + fun remove(origin: BlockKey, destination: BlockKey): T? { + return synchronized(lock) { + pathCache.remove(origin, destination)?.getOrNull() + } + } + + fun getOrCompute(origin: BlockKey, destination: BlockKey, provier: () -> T?): T? { + if (contains(origin, destination)) return get(origin, destination) + + val result = provier() + set(origin, destination, result) + return result + } + + fun invalidatePaths(pos: BlockKey, node: Node) { + val toRemove = mutableSetOf>() + + // If the pos is an origin or destination, there is no need to perform a flood to find the connected rows / destinations + // If the path cache contains a row at this pos, an origin is present here, and it can be removed + if (pathCache.containsRow(pos)) { + pathCache.rowMap()[pos]?.keys?.forEach { columnKey -> + toRemove.add(pos to columnKey) + } + } + + // If the path cache contains a column at this pos, a destination from an origin within the chunk can be invalidated + if (pathCache.containsColumn(pos)) { + pathCache.columnMap()[pos]?.keys?.forEach { rowKey -> + toRemove.add(rowKey to pos) + } + } + + // Perform a flood fill to find all network destinations, then remove all destination columns + cache.getNetworkDestinations(clazz = cache.extractorNodeClass, originPos = pos, originNode = node) { + // Traverse network backwards + getPreviousNodes(cache.holder.nodeProvider, null) + }.forEach { extractorPos -> + pathCache.rowMap()[extractorPos]?.keys?.forEach { columnKey -> + toRemove.add(extractorPos to columnKey) + } + } + + // Remove all the paths after being found + synchronized(lock) { + for ((rowKey, columnKey) in toRemove) pathCache.remove(rowKey, columnKey) + } + } + + companion object { + fun standard(cache: TransportCache): PathCache = PathCache(cache) + fun keyed(cache: TransportCache): PathCache>> = PathCache(cache) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 9f53c90114..29684966e7 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.transport.util import it.unimi.dsi.fastutil.longs.Long2IntRBTreeMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet +import net.horizonsend.ion.server.command.misc.TransportDebugCommand import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.transport.nodes.types.Node import net.horizonsend.ion.server.features.world.chunk.IonChunk @@ -73,7 +74,12 @@ fun getIdealPath( iterations++ val current = queue.minBy { it.f } - if (current.node.position == destination) return current.buildPath() + if (current.node.position == destination) { + val path = current.buildPath() + TransportDebugCommand.idealNumbers.offer(path.size) + TransportDebugCommand.stepNumbers.offer(iterations) + return path + } queueRemove(current) markVisited(current) From b393ce1c3702e93bdec766096cef585023187c55 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:08:40 -0600 Subject: [PATCH 475/500] Shift click to not open menus --- .../features/custom/blocks/extractor/CustomExtractorBlock.kt | 1 + .../server/features/custom/blocks/filter/CustomFilterBlock.kt | 1 + 2 files changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index 9fd4704496..347b1fbd31 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -31,6 +31,7 @@ abstract class CustomExtractorBlock( } override fun onRightClick(event: PlayerInteractEvent, block: Block) { + if (event.player.isSneaking) return val chunk = IonChunk[block.world, block.x.shr(4), block.z.shr(4)] ?: return val key = toBlockKey(block.x, block.y, block.z) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt index 76f0aec193..af94cf55ed 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -27,6 +27,7 @@ abstract class CustomFilterBlock( val cooldown = PerPlayerCooldown(5L) override fun onRightClick(event: PlayerInteractEvent, block: Block) { + if (event.player.isSneaking) return event.isCancelled = true event.player.closeInventory() From 055c36d85e9ff3ea8d7c3883092fed08160fd39c Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:56:28 -0600 Subject: [PATCH 476/500] More robust cache invalidation --- .../server/features/transport/NewTransport.kt | 36 ++++++++++++------- .../transport/nodes/cache/NodeCacheFactory.kt | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt index 5d5ceeaf90..853e88180d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/NewTransport.kt @@ -18,6 +18,7 @@ import org.bukkit.block.data.BlockData import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.block.BlockBreakEvent +import org.bukkit.event.block.BlockFromToEvent import org.bukkit.event.block.BlockPistonExtendEvent import org.bukkit.event.block.BlockPistonRetractEvent import org.bukkit.event.block.BlockPlaceEvent @@ -122,50 +123,61 @@ object NewTransport : IonServerComponent(runAfterTick = true /* Run after tick t } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun onPlayerBlockPlace(event: BlockPlaceEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, event.blockReplacedState.blockData, block.blockData) } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun onPlayerBlockBreak(event: BlockBreakEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, block.blockData, Material.AIR.createBlockData()) } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun onShipBlockPlace(event: StarshipPlaceBlockEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, Material.AIR.createBlockData(), block.blockData) } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun onShipBlockBreak(event: StarshipBreakBlockEvent) { val block = event.block handleBlockEvent(block.world, block.x, block.y, block.z, event.block.blockData, Material.AIR.createBlockData()) } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun handlePistonExtend(event: BlockPistonExtendEvent) { - val piston = event.block - Tasks.sync { + Tasks.async { + val piston = event.block + invalidateCache(piston.world, piston.x, piston.y, piston.z) + for (block in event.blocks) { - ensureExtractor(piston.world, piston.x, piston.y, piston.z) + ensureExtractor(block.world, block.x, block.y, block.z) + invalidateCache(block.world, block.x, block.y, block.z) } } } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun handlePistonRetract(event: BlockPistonRetractEvent) { - val piston = event.block - Tasks.sync { + Tasks.async { + val piston = event.block + invalidateCache(piston.world, piston.x, piston.y, piston.z) + for (block in event.blocks) { - ensureExtractor(piston.world, piston.x, piston.y, piston.z) + ensureExtractor(block.world, block.x, block.y, block.z) + invalidateCache(block.world, block.x, block.y, block.z) } } } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + fun handleWaterFlow(event: BlockFromToEvent) { + invalidateCache(event.block.world, event.block.x, event.block.y, event.block.z) + } + fun saveExtractors() { for (world in Bukkit.getWorlds().map { it.ion }) { world.getAllChunks().values.forEach { chunk -> diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt index f30dbc0f84..6c89243e8d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/NodeCacheFactory.kt @@ -27,7 +27,7 @@ class NodeCacheFactory private constructor(private val materialHandlers: Multima return filtered.firstNotNullOfOrNull { handler -> handler.construct(blockData, toBlockKey(block.x, block.y, block.z), holder) } } - class Builder { + class Builder { val materialHandlers = multimapOf>() inline fun addDataHandler(material: Material, noinline constructor: (T, BlockKey, CacheHolder<*>) -> Node?): Builder { From 1750c409e08fc2070e20f4b83760a7ea4286f4f7 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:59:31 -0600 Subject: [PATCH 477/500] don't go all the way up to the line when backing up multis --- .../ion/server/features/multiblock/MultiblockEntities.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt index eb3a0ac717..1bd4583716 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockEntities.kt @@ -22,6 +22,7 @@ import org.bukkit.block.Block import org.bukkit.block.Sign as SignState import org.bukkit.block.data.type.WallSign as WallSignData import org.bukkit.event.EventHandler +import java.util.concurrent.TimeUnit /** * Provides utility functions for multiblock entities, and handles sign backups @@ -139,15 +140,17 @@ object MultiblockEntities : IonServerComponent() { new?.saveToSign() } + val msptBuffer = TimeUnit.MILLISECONDS.toNanos(5) + @EventHandler fun onTickEnd(event: ServerTickEndEvent) { - if (event.timeRemaining < 0) return + if (event.timeRemaining < msptBuffer) return MultiblockTicking.iterateManagers { manager -> if (manager.getSignUnsavedTime() < 5000L) return@iterateManagers for (keyEntity in manager.getAllMultiblockEntities()) { - if (event.timeRemaining < 0) return + if (event.timeRemaining < msptBuffer) return keyEntity.value.saveToSign() } From cd89d226e78a5d13e4af0d5847e300fdb26f59c3 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:25:42 -0600 Subject: [PATCH 478/500] Right comes before left in nms --- .../features/transport/nodes/cache/ItemTransportCache.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt index 6c0cdde25f..a250e48e48 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/ItemTransportCache.kt @@ -250,9 +250,9 @@ class ItemTransportCache(override val holder: CacheHolder): return CraftInventory(entity) } - val left = if (type == ChestType.LEFT) entity else otherEntity val right = if (type == ChestType.RIGHT) entity else otherEntity - return CraftInventoryDoubleChest(CompoundContainer(left, right)) + val left = if (type == ChestType.LEFT) entity else otherEntity + return CraftInventoryDoubleChest(CompoundContainer(right, left)) } else -> { CraftInventory(entity) From 11751f16d078264ae99b9750de13232eb12ee243 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:53:05 -0600 Subject: [PATCH 479/500] add callback when placing custom block --- .../ion/server/features/custom/blocks/CustomBlocks.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index c5939698b0..4f29194b90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -243,6 +243,8 @@ open class CustomBlock( private val customBlockItem: Supplier ) { val customItem get() = customBlockItem.get() + + open fun placeCallback(placedItem: ItemStack, block: Block) {} } data class BlockLoot( From 535382fd611d632041e844db6b1a261e646a4620 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:55:03 -0600 Subject: [PATCH 480/500] when placing grab the filter & extractor data from the item --- .../features/custom/blocks/CustomBlockListeners.kt | 6 +++--- .../blocks/extractor/AdvancedItemExtractorBlock.kt | 13 +++++++++++++ .../custom/blocks/filter/ItemFilterBlock.kt | 13 ++++++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt index 2985c7e656..2c4184109c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt @@ -10,7 +10,6 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl import org.bukkit.GameMode import org.bukkit.Material import org.bukkit.attribute.Attribute -import org.bukkit.block.data.BlockData import org.bukkit.enchantments.Enchantment import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority @@ -30,9 +29,10 @@ object CustomBlockListeners : SLEventListener() { val hand = event.hand val itemStack = player.inventory.getItem(hand).clone() val item: CustomBlockItem = itemStack.customItem as? CustomBlockItem ?: return - val blockData: BlockData = item.getCustomBlock().blockData + val block = item.getCustomBlock() - event.block.location.block.setBlockData(blockData, true) + event.block.location.block.setBlockData(block.blockData, true) + block.placeCallback(event.block) } val noDropEvents: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index bff47b13bd..01d9df4b2a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -10,14 +10,18 @@ import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI.Comp import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block +import org.bukkit.block.TileState import org.bukkit.block.data.type.CreakingHeart import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper import xyz.xenondevs.invui.gui.Gui import xyz.xenondevs.invui.item.impl.AbstractItem @@ -46,6 +50,15 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( AdvancedItemExtractorGUI(player, block, extractorData).open() } + override fun placeCallback(placedItem: ItemStack, block: Block) { + val extractorData = placedItem.persistentDataContainer.get(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer) ?: return + + val state = block.state + if (state !is TileState) return + + state.persistentDataContainer.set(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer, extractorData) + } + class AdvancedItemExtractorGUI(val viewer: Player, val block: Block, val extractorData: ItemExtractorData) : GuiWrapper { override fun open() { val gui = Gui.normal() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index 5666ba67a3..01e2acba0b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -8,10 +8,12 @@ import net.horizonsend.ion.server.features.gui.custom.filter.ItemFilterGui import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block +import org.bukkit.block.TileState import org.bukkit.block.data.type.CreakingHeart import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack @@ -39,8 +41,17 @@ object ItemFilterBlock : CustomFilterBlock( player: Player, block: Block, filterData: FilterData, - tileState: Supplier + tileState: Supplier ): GuiWrapper { return ItemFilterGui(player, filterData, tileState) } + + override fun placeCallback(placedItem: ItemStack, block: Block) { + val storedFilterData = placedItem.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return + + val state = block.state + if (state !is TileState) return + + state.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, storedFilterData) + } } From ee3171d00bbc25fba7adb9992c247598b36bdf46 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 18:16:04 -0600 Subject: [PATCH 481/500] Allow wrench to pick up filters & Extractors, fix filter method saving --- .../custom/blocks/CustomBlockListeners.kt | 2 +- .../features/custom/blocks/WrenchRemovable.kt | 8 +++++ .../extractor/AdvancedItemExtractorBlock.kt | 6 ++++ .../blocks/extractor/CustomExtractorBlock.kt | 34 ++++++++++++++++-- .../custom/blocks/filter/CustomFilterBlock.kt | 36 ++++++++++++++++++- .../custom/blocks/filter/ItemFilterBlock.kt | 10 ------ .../features/custom/items/misc/Wrench.kt | 29 +++++++++++++-- .../gui/custom/filter/ItemFilterGui.kt | 2 ++ .../features/transport/filters/FilterEntry.kt | 4 +-- .../features/transport/filters/FilterMeta.kt | 5 +-- .../features/transport/filters/FilterType.kt | 22 +++++++++--- .../manager/extractors/ExtractorManager.kt | 2 +- .../ion/server/miscellaneous/utils/Items.kt | 2 ++ 13 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt index 2c4184109c..e5b67d9527 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt @@ -32,7 +32,7 @@ object CustomBlockListeners : SLEventListener() { val block = item.getCustomBlock() event.block.location.block.setBlockData(block.blockData, true) - block.placeCallback(event.block) + block.placeCallback(itemStack, event.block) } val noDropEvents: ConcurrentHashMap.KeySetView = ConcurrentHashMap.newKeySet() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt new file mode 100644 index 0000000000..e4448f541e --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt @@ -0,0 +1,8 @@ +package net.horizonsend.ion.server.features.custom.blocks + +import org.bukkit.block.Block +import org.bukkit.inventory.ItemStack + +interface WrenchRemovable { + fun decorateItem(itemStack: ItemStack, block: Block) +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 01d9df4b2a..62ec1a4781 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -9,6 +9,7 @@ import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.gui.interactable.InteractableGUI.Companion.setTitle import net.horizonsend.ion.server.features.transport.items.SortingOrder import net.horizonsend.ion.server.features.transport.manager.extractors.ExtractorManager +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ItemExtractorData import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys @@ -46,6 +47,10 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( return ItemExtractorData(pos, ItemExtractorData.ItemExtractorMetaData(pos)) } + override fun createExtractorData(pos: BlockKey, metaData: ExtractorMetaData): ItemExtractorData { + return ItemExtractorData(pos, metaData as ItemExtractorData.ItemExtractorMetaData) + } + override fun openGUI(player: Player, block: Block, extractorData: ItemExtractorData) { AdvancedItemExtractorGUI(player, block, extractorData).open() } @@ -57,6 +62,7 @@ object AdvancedItemExtractorBlock : CustomExtractorBlock( if (state !is TileState) return state.persistentDataContainer.set(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer, extractorData) + state.update() } class AdvancedItemExtractorGUI(val viewer: Player, val block: Block, val extractorData: ItemExtractorData) : GuiWrapper { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index 347b1fbd31..9f2d71c8a2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -1,19 +1,30 @@ package net.horizonsend.ion.server.features.custom.blocks.extractor +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.common.utils.text.orEmpty import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock +import net.horizonsend.ion.server.features.custom.blocks.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData +import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getCustomName +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer +import net.kyori.adventure.text.Component import org.bukkit.block.Block +import org.bukkit.block.TileState import org.bukkit.block.data.BlockData import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack import java.util.function.Supplier import kotlin.reflect.KClass @@ -23,11 +34,11 @@ abstract class CustomExtractorBlock( drops: BlockLoot, customBlockItem: Supplier, val extractorDataType: KClass -) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { +) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem), WrenchRemovable { val cooldown = PerPlayerCooldown(5L) - fun load(container: MetaDataContainer<*, *>): T { - return PDCSerializers.unpack(container) + fun load(key: BlockKey, container: MetaDataContainer<*, *>): T { + return createExtractorData(key, PDCSerializers.unpack(container)) } override fun onRightClick(event: PlayerInteractEvent, block: Block) { @@ -53,5 +64,22 @@ abstract class CustomExtractorBlock( abstract fun createExtractorData(pos: BlockKey): T + abstract fun createExtractorData(pos: BlockKey, metaData: ExtractorMetaData): T + abstract fun openGUI(player: Player, block: Block, extractorData: T) + + override fun decorateItem(itemStack: ItemStack, block: Block) { + val state = block.state + state as TileState + + val data = state.persistentDataContainer.get(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer) ?: return + + val customDisplayName = itemStack.getCustomName() + + itemStack + .updateDisplayName(ofChildren(customDisplayName.orEmpty(), Component.text(" (Configured)"))) + .updatePersistentDataContainer { + set(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer, data) + } + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt index af94cf55ed..412aecfd0a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -1,21 +1,30 @@ package net.horizonsend.ion.server.features.custom.blocks.filter +import net.horizonsend.ion.common.utils.text.ofChildren +import net.horizonsend.ion.common.utils.text.orEmpty import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock +import net.horizonsend.ion.server.features.custom.blocks.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.world.chunk.IonChunk +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.PerPlayerCooldown import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.horizonsend.ion.server.miscellaneous.utils.getCustomName +import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName +import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer +import net.kyori.adventure.text.Component import org.bukkit.block.Block import org.bukkit.block.TileState import org.bukkit.block.data.BlockData import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack import java.util.function.Supplier abstract class CustomFilterBlock( @@ -23,7 +32,7 @@ abstract class CustomFilterBlock( blockData: BlockData, drops: BlockLoot, customBlockItem: Supplier -) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem) { +) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem), WrenchRemovable { val cooldown = PerPlayerCooldown(5L) override fun onRightClick(event: PlayerInteractEvent, block: Block) { @@ -51,4 +60,29 @@ abstract class CustomFilterBlock( abstract fun createData(pos: BlockKey): FilterData abstract fun getGui(player: Player, block: Block, filterData: FilterData, tileState: Supplier) : GuiWrapper + + override fun decorateItem(itemStack: ItemStack, block: Block) { + val state = block.state + state as TileState + + val data = state.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return + + val customDisplayName = itemStack.getCustomName() + + itemStack + .updateDisplayName(ofChildren(customDisplayName.orEmpty(), Component.text(" (Configured)"))) + .updatePersistentDataContainer { + set(NamespacedKeys.FILTER_DATA, FilterData, data) + } + } + + override fun placeCallback(placedItem: ItemStack, block: Block) { + val storedFilterData = placedItem.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return + + val state = block.state + if (state !is TileState) return + + state.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, storedFilterData) + state.update() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index 01e2acba0b..d94d503cce 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -8,7 +8,6 @@ import net.horizonsend.ion.server.features.gui.custom.filter.ItemFilterGui import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType -import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.Material @@ -45,13 +44,4 @@ object ItemFilterBlock : CustomFilterBlock( ): GuiWrapper { return ItemFilterGui(player, filterData, tileState) } - - override fun placeCallback(placedItem: ItemStack, block: Block) { - val storedFilterData = placedItem.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return - - val state = block.state - if (state !is TileState) return - - state.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, storedFilterData) - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index 5495e11edd..bbd6ec3da3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -2,6 +2,10 @@ package net.horizonsend.ion.server.features.custom.items.misc import net.horizonsend.ion.common.extensions.information import net.horizonsend.ion.server.command.misc.MultiblockCommand +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock +import net.horizonsend.ion.server.features.custom.blocks.CustomBlockListeners +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.custom.blocks.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager @@ -12,8 +16,11 @@ import net.horizonsend.ion.server.features.multiblock.MultiblockAccess import net.horizonsend.ion.server.features.multiblock.PrePackaged import net.horizonsend.ion.server.miscellaneous.utils.isWallSign import net.kyori.adventure.text.Component.text +import org.bukkit.Material +import org.bukkit.block.Block import org.bukkit.block.Sign import org.bukkit.entity.Player +import org.bukkit.event.block.BlockBreakEvent import org.bukkit.event.player.PlayerInteractEvent object Wrench : CustomItem( @@ -25,7 +32,7 @@ object Wrench : CustomItem( ) { override val customComponents: CustomItemComponentManager = CustomItemComponentManager(serializationManager).apply { addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, rightClickListener(this@Wrench) { event, _, itemStack -> - handleSecondaryInteract(event.player, event) + handleRightClick(event.player, event) }) addComponent(CustomComponentTypes.LISTENER_PLAYER_INTERACT, leftClickListener(this@Wrench) { event, _, itemStack -> @@ -48,14 +55,32 @@ object Wrench : CustomItem( MultiblockCommand.onCheck(player, multiblock, sign.x, sign.y, sign.z) } - private fun handleSecondaryInteract(player: Player, event: PlayerInteractEvent?) { + private fun handleRightClick(player: Player, event: PlayerInteractEvent?) { val clickedBlock = event?.clickedBlock ?: return val state = clickedBlock.state + val customBlock = CustomBlocks.getByBlockData(clickedBlock.blockData) if (player.isSneaking && state is Sign) return tryPickUpMultiblock(player, state) + if (player.isSneaking && customBlock is WrenchRemovable) return tryPickUpBlock(player, clickedBlock, customBlock) } private fun tryPickUpMultiblock(player: Player, sign: Sign) { PrePackaged.pickUpStructure(player, sign) } + + private fun tryPickUpBlock(player: Player, block: Block, customBlock: WrenchRemovable) { + val event = BlockBreakEvent(block, player) + CustomBlockListeners.noDropEvents.add(event) + + if (!event.callEvent()) return + + val item = (customBlock as CustomBlock).customItem.constructItemStack() + customBlock.decorateItem(item, block) + + block.type = Material.AIR + block.world.dropItem( + block.location.toCenterLocation(), + item + ) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt index 41b65b4a54..1e4c2f4ffc 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/custom/filter/ItemFilterGui.kt @@ -34,6 +34,8 @@ class ItemFilterGui(val viewer: Player, private val data: FilterData data.isWhitelist = !data.isWhitelist updateSlotOverlay(event.view) + + FilterManager.save(tileState.get(), data) } override fun open() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt index fa54f3ac41..ff8d86bc4d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterEntry.kt @@ -25,12 +25,12 @@ data class FilterEntry(var value: T?, val type: FilterT val filterTypeIdentifier = primitive.get(NamespacedKeys.FILTER_TYPE, PersistentDataType.STRING)!! val filterType = FilterType[filterTypeIdentifier] - val meta = primitive.get(NamespacedKeys.FILTER_META, PersistentDataType.TAG_CONTAINER) + val meta = primitive.get(NamespacedKeys.FILTER_META, MetaDataContainer) return FilterEntry( filterType.retrieveValue(primitive), filterType, - meta?.let { filterType.retrieveMeta(meta, context) } ?: filterType.buildEmptyMeta() + meta?.let { filterType.retrieveMeta(meta) } ?: filterType.buildEmptyMeta() ) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt index 38704d0661..4edb6312ee 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterMeta.kt @@ -17,8 +17,9 @@ interface FilterMeta { return pdc } - override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext, ): ItemFilterMeta { - return ItemFilterMeta(primitive.getOrDefault(NamespacedKeys.SORTING_METHOD, enumType, FilterMethod.LENIENT)) + override fun fromPrimitive(primitive: PersistentDataContainer, context: PersistentDataAdapterContext): ItemFilterMeta { + val sortingMethod = primitive.get(NamespacedKeys.SORTING_METHOD, enumType)!! + return ItemFilterMeta(sortingMethod) } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt index 5bcb884f15..dc4ad0b827 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/filters/FilterType.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilt import net.horizonsend.ion.server.features.transport.fluids.Fluid import net.horizonsend.ion.server.features.transport.fluids.FluidPersistentDataType import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.MetaDataContainer import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.registrations.persistence.PDCSerializers import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName @@ -42,8 +43,9 @@ abstract class FilterType( return pdc.get(NamespacedKeys.FILTER_ENTRY, persistentDataType) } - fun retrieveMeta(pdc: PersistentDataContainer, context: PersistentDataAdapterContext): M { - return metaType.loadMetaDataContainer(pdc, context).data + fun retrieveMeta(container: MetaDataContainer<*, *>): M { + @Suppress("UNCHECKED_CAST") + return container.data as M } abstract fun buildEmptyMeta(): M @@ -72,7 +74,13 @@ abstract class FilterType( abstract fun toItem(entry: FilterEntry): ItemStack? - data object FluidType : FilterType(CacheType.FLUID, "FLUID", Fluid::class.java, FluidPersistentDataType, PDCSerializers.EMPTY_FILTER_META) { + data object FluidType : FilterType( + cacheType = CacheType.FLUID, + identifier = "FLUID", + typeClass = Fluid::class.java, + persistentDataType = FluidPersistentDataType, + metaType = PDCSerializers.EMPTY_FILTER_META + ) { override fun toItem(entry: FilterEntry): ItemStack? { val value = entry.value if (value == null) return null @@ -94,7 +102,13 @@ abstract class FilterType( } } - data object ItemType : FilterType(CacheType.ITEMS, "ITEMS", ItemStack::class.java, ItemSerializer, PDCSerializers.ITEM_FILTER_META) { + data object ItemType : FilterType( + cacheType = CacheType.ITEMS, + identifier = "ITEMS", + typeClass = ItemStack::class.java, + persistentDataType = ItemSerializer, + metaType = PDCSerializers.ITEM_FILTER_META + ) { override fun toItem(entry: FilterEntry): ItemStack? = entry.value?.clone() override fun buildEmptyMeta(): ItemFilterMeta = ItemFilterMeta() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt index d86e6405c6..4183902c66 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/extractors/ExtractorManager.kt @@ -52,7 +52,7 @@ abstract class ExtractorManager { val stored = pdc?.get(NamespacedKeys.COMPLEX_EXTRACTORS, MetaDataContainer) if (stored != null) { - return customBlock.load(stored) + return customBlock.load(pos, stored) } return customBlock.createExtractorData(pos) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt index 274e3ab9cc..8b5dc0a3b2 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/utils/Items.kt @@ -45,6 +45,8 @@ fun ItemStack.updateDisplayName(name: Component): ItemStack { return this } +fun ItemStack.getCustomName(): Component? = getData(DataComponentTypes.CUSTOM_NAME) + @Deprecated("use components") fun ItemStack.setLoreAndGetString(lines: List): ItemStack = apply { this.lore = lines } From bb1bbd525bbb3c887ca50c1720ca54cb7bba039b Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Sun, 2 Feb 2025 18:18:18 -0600 Subject: [PATCH 482/500] dont consume packaged multis in creative --- .../server/features/custom/items/misc/MultiblockToken.kt | 6 +++++- .../server/features/custom/items/misc/PackagedMultiblock.kt | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt index ef90c9c114..ee3879fcaf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/MultiblockToken.kt @@ -19,6 +19,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text +import org.bukkit.GameMode import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack @@ -66,6 +67,9 @@ object MultiblockToken : CustomItem( } runCatching { PrePackaged.place(livingEntity, origin, livingEntity.facing, packagedData, null, null) } - itemStack.amount-- + + if (event.player.gameMode != GameMode.CREATIVE) { + itemStack.amount-- + } } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt index 4d25598862..21f588359e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/PackagedMultiblock.kt @@ -23,6 +23,7 @@ import net.horizonsend.ion.server.miscellaneous.utils.updateData import net.horizonsend.ion.server.miscellaneous.utils.updateDisplayName import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContainer import net.kyori.adventure.text.Component.text +import org.bukkit.GameMode import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent @@ -91,7 +92,9 @@ object PackagedMultiblock : CustomItem( } } - itemStack.amount-- + if (event.player.gameMode != GameMode.CREATIVE) { + itemStack.amount-- + } } fun tryPreview(livingEntity: LivingEntity, itemStack: ItemStack, event: PlayerInteractEvent) { From 8cf3a4292c56c8bc06d7c3ebede651797fc2a5bc Mon Sep 17 00:00:00 2001 From: kwazedilla Date: Mon, 3 Feb 2025 01:09:47 -0800 Subject: [PATCH 483/500] change advanced item extractor model --- .../ion/server/features/custom/items/CustomItemRegistry.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index 35f25e6d39..f8b0629151 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -329,7 +329,7 @@ object CustomItemRegistry : IonServerComponent() { val WRENCH = register(Wrench) - val ADVANCED_ITEM_EXTRACTOR = customBlockItem("ADVANCED_ITEM_EXTRACTOR", "tool/multiblock_workbench", text("Advanced Item Extractor"), CustomBlocks::ADVANCED_ITEM_EXTRACTOR) + val ADVANCED_ITEM_EXTRACTOR = customBlockItem("ADVANCED_ITEM_EXTRACTOR", "misc/advanced_item_extractor", text("Advanced Item Extractor"), CustomBlocks::ADVANCED_ITEM_EXTRACTOR) val ITEM_FILTER = customBlockItem("ITEM_FILTER", "tool/multiblock_workbench", text("Item Filter"), CustomBlocks::ITEM_FILTER) private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( From acd3806b30472a2af4cf5bdff399ccba8dbb8c38 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Mon, 3 Feb 2025 13:53:27 -0600 Subject: [PATCH 484/500] base of ship factory v2 --- .../multiblock/MultiblockRegistration.kt | 2 + .../manager/ChunkMultiblockManager.kt | 2 + .../multiblock/manager/MultiblockManager.kt | 3 + .../manager/ShipMultiblockManager.kt | 3 + .../misc/AdvancedShipFactoryMultiblock.kt | 229 ++++++++++++++++++ .../transport/manager/holders/CacheHolder.kt | 4 +- .../manager/holders/ChunkCacheHolder.kt | 6 + .../manager/holders/ShipCacheHolder.kt | 4 + 8 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index 72fc502ed7..fd54f4f787 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -40,6 +40,7 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMu import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.AdvancedShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock @@ -375,6 +376,7 @@ object MultiblockRegistration : IonServerComponent() { // Machine registerMultiblock(ShipFactoryMultiblock) + registerMultiblock(AdvancedShipFactoryMultiblock) registerMultiblock(DecomposerMultiblock) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt index ae968b3884..74fcb64867 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ChunkMultiblockManager.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultibloc import net.horizonsend.ion.server.features.multiblock.entity.linkages.MultiblockLinkageManager import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType @@ -24,6 +25,7 @@ class ChunkMultiblockManager(val chunk: IonChunk, log: Logger) : MultiblockManag override val world: World = chunk.world override fun getInputManager(): InputManager = chunk.world.ion.inputManager override fun getLinkageManager(): MultiblockLinkageManager = chunk.world.ion.multiblockManager.linkageManager + override fun getTransportManager(): TransportManager<*> = chunk.transportNetwork /** * Logic upon the chunk being saved diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt index 03e216830e..7ab249af7f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/MultiblockManager.kt @@ -8,6 +8,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.linkages.Multiblock import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.AsyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType @@ -40,6 +41,8 @@ abstract class MultiblockManager(val log: Logger) { abstract fun getLinkageManager(): MultiblockLinkageManager + abstract fun getTransportManager(): TransportManager<*> + abstract fun save() abstract fun markChanged() diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt index 8a17d2066f..beabeb3a05 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/manager/ShipMultiblockManager.kt @@ -14,6 +14,7 @@ import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTic import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock import net.horizonsend.ion.server.features.starship.Starship import net.horizonsend.ion.server.features.starship.movement.StarshipMovement +import net.horizonsend.ion.server.features.transport.manager.TransportManager import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.inputs.InputManager import net.horizonsend.ion.server.features.transport.util.CacheType @@ -45,6 +46,8 @@ class ShipMultiblockManager(val starship: Starship) : MultiblockManager(IonServe return starship.transportManager.getInputProvider() } + override fun getTransportManager(): TransportManager<*> = starship.transportManager + override fun getLinkageManager(): MultiblockLinkageManager { return multiblockLinkageManager } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt new file mode 100644 index 0000000000..88a71b3bac --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt @@ -0,0 +1,229 @@ +package net.horizonsend.ion.server.features.multiblock.type.misc + +import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers +import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler +import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule +import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage +import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity +import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager +import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.misc.AdvancedShipFactoryMultiblock.AdvancedShipFactoryEntity +import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset +import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData +import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode +import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData +import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.BACKWARD +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.FORWARD +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.Vec3i +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.toBlockKey +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import org.bukkit.Material +import org.bukkit.World +import org.bukkit.block.BlockFace +import org.bukkit.block.Sign +import org.bukkit.block.data.Bisected +import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.persistence.PersistentDataAdapterContext + +object AdvancedShipFactoryMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock, InteractableMultiblock { + override val name: String = "shipfactory" + + override val signText = createSignText( + line1 = text("Starship Factory", NamedTextColor.BLUE), + line2 = text("Advanced", NamedTextColor.YELLOW), + line3 = null, + line4 = null + ) + + override val displayName: Component get() = text("Advanced Ship Factory") + override val description: Component get() = text("Print starships and other structures with materials and credits. Provides more configuration settings.") + + override fun MultiblockShape.buildStructure() { + z(2) { + y(-1) { + x(2).anyStairs(PrepackagedPreset.stairs(BACKWARD, Bisected.Half.TOP, shape = STRAIGHT)) + x(1).ironBlock() + x(0).anyGlass() + x(-1).ironBlock() + x(-2).anyStairs(PrepackagedPreset.stairs(BACKWARD, Bisected.Half.TOP, shape = STRAIGHT)) + } + y(0) { + x(2).anyStairs(PrepackagedPreset.stairs(BACKWARD, Bisected.Half.BOTTOM, shape = STRAIGHT)) + x(1).ironBlock() + x(0).anyGlass() + x(-1).ironBlock() + x(-2).anyStairs(PrepackagedPreset.stairs(BACKWARD, Bisected.Half.BOTTOM, shape = STRAIGHT)) + } + } + z(1) { + y(-1) { + x(2).anyGlass() + x(1).anyGlass() + x(0).sponge() + x(-1).anyGlass() + x(-2).anyGlass() + } + y(0) { + x(2).anyPipedInventory() + x(1).sponge() + x(0).type(Material.LODESTONE) + x(-1).sponge() + x(-2).anyPipedInventory() + } + } + z(0) { + y(-1) { + x(2).anyStairs(PrepackagedPreset.stairs(FORWARD, Bisected.Half.TOP, shape = STRAIGHT)) + x(1).ironBlock() + x(0).powerInput() + x(-1).ironBlock() + x(-2).anyStairs(PrepackagedPreset.stairs(FORWARD, Bisected.Half.TOP, shape = STRAIGHT)) + } + y(0) { + x(2).anyStairs(PrepackagedPreset.stairs(FORWARD, Bisected.Half.BOTTOM, shape = STRAIGHT)) + x(1).ironBlock() + x(0).anyGlass() + x(-1).ironBlock() + x(-2).anyStairs(PrepackagedPreset.stairs(FORWARD, Bisected.Half.BOTTOM, shape = STRAIGHT)) + } + } + } + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val entity = getMultiblockEntity(sign) ?: return + entity.openMenu(player) + } + + override fun createEntity( + manager: MultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + structureDirection: BlockFace, + ): AdvancedShipFactoryEntity { + return AdvancedShipFactoryEntity(data, manager, x, y, z, world, structureDirection) + } + + class AdvancedShipFactoryEntity( + data: PersistentMultiblockData, + manager: MultiblockManager, + x: Int, + y: Int, + z: Int, + world: World, + structureDirection: BlockFace, + ) : MultiblockEntity(manager, AdvancedShipFactoryMultiblock, world, x, y, z, structureDirection), StatusTickedMultiblockEntity, SyncTickingMultiblockEntity, PoweredMultiblockEntity, UserManagedMultiblockEntity, DisplayMultiblockEntity { + override val multiblock: AdvancedShipFactoryMultiblock = AdvancedShipFactoryMultiblock + + override val maxPower: Int = 300_000 + override val powerStorage: PowerStorage = loadStoredPower(data) + + override val userManager: UserManagedMultiblockEntity.UserManager = UserManagedMultiblockEntity.UserManager(data, true) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(5) + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() + + override val displayHandler: TextDisplayHandler = DisplayHandlers.newMultiblockSignOverlay( + this, + { PowerEntityDisplayModule(it, this) }, + { StatusDisplayModule(it, statusManager) } + ).register() + + override val inputsData: InputsData = InputsData.Builder(this) + .addPowerInput(0, -1, 0) + .build() + + fun openMenu(player: Player) { + if (userManager.currentlyUsed()) { + userManager.clear() + return + } + + userManager.setUser(player) + } + + override fun tick() { + if (!userManager.currentlyUsed()) return + println("Toggled on") + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + userManager.saveUserData(store) + savePowerData(store) + } + + private val pipeInputOffsets = arrayOf( + Vec3i(0, 0, 0), + Vec3i(0, 0, 2), + Vec3i(-2, -1, 1), + Vec3i(+2, -1, 1), + ) + + fun getNetworkedExtractors(): Map> { + val transportManager = manager.getTransportManager() + val itemCacheHolder = transportManager.itemPipeManager + + val localPipeInputKeys = pipeInputOffsets.map { i -> toBlockKey(getPosRelative(i.x, i.y, i.z)) } + + val allDestinations = localPipeInputKeys.associateWith { inputLoc -> + val node = itemCacheHolder.nodeProvider.invoke(CacheType.ITEMS, world, inputLoc) ?: return@associateWith listOf() + + itemCacheHolder.cache.getNetworkDestinations( + clazz = ItemNode.ItemExtractorNode::class, + originPos = inputLoc, + originNode = node + ) { + getPreviousNodes(itemCacheHolder.nodeProvider, null) + } + } + + return allDestinations + } + + fun canRemoveFromDestination(destination: BlockKey, sourceLoc: BlockKey, stack: ItemStack): Boolean { + val localCacheHolder = manager.getTransportManager().itemPipeManager.getCacheHolderAt(destination) ?: return false + val destinationInventory = localCacheHolder.cache.getInventory(destination) ?: return false + + if (!destinationInventory.containsAtLeast(stack, stack.amount)) return false + val singletonItem = stack.asOne() + + val path = localCacheHolder.cache.findPath( + origin = NodePositionData( + ItemNode.ItemExtractorNode, + world, + destination, + BlockFace.SELF + ), + destination = sourceLoc, + itemStack = singletonItem, + ) { node, blockFace -> + if (node !is ItemNode.FilterNode) return@findPath true + + node.matches(singletonItem) + } + + return path != null + } + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt index 4ef4deee2a..3e0693535d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/CacheHolder.kt @@ -10,7 +10,7 @@ import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.World -interface CacheHolder { +interface CacheHolder { val transportManager: TransportManager<*> val cache: T @@ -44,5 +44,7 @@ interface CacheHolder { fun getInputManager(): InputManager + fun getCacheHolderAt(key: BlockKey): CacheHolder? + val nodeProvider: (CacheType, World, BlockKey) -> Node? } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt index af9c10d3f7..7e0524ca1a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ChunkCacheHolder.kt @@ -64,4 +64,10 @@ class ChunkCacheHolder private constructor (override val tran override fun getInputManager(): InputManager { return transportManager.getInputProvider() } + + override fun getCacheHolderAt(key: BlockKey): CacheHolder? { + val chunk = IonChunk[getWorld(), getX(key).shr(4), getZ(key).shr(4)] ?: return null + @Suppress("UNCHECKED_CAST") + return cache.type.get(chunk).holder as CacheHolder + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt index 99a43b88b4..f5f4bb6655 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/manager/holders/ShipCacheHolder.kt @@ -73,4 +73,8 @@ class ShipCacheHolder(override val transportManager: ShipTran override fun getInputManager(): InputManager { return transportManager.inputManager } + + override fun getCacheHolderAt(key: BlockKey): CacheHolder { + return this + } } From b64993860ecec01923b5fa1abf8e59a4bbdc82d9 Mon Sep 17 00:00:00 2001 From: kwazedilla Date: Tue, 4 Feb 2025 00:25:46 -0800 Subject: [PATCH 485/500] item filter model (and move multiblock workbench model) --- .../ion/server/features/custom/items/CustomItemRegistry.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt index f8b0629151..bd22749350 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/CustomItemRegistry.kt @@ -324,13 +324,13 @@ object CustomItemRegistry : IonServerComponent() { val MULTIBLOCK_WORKBENCH = register(CustomBlockItem( identifier = "MULTIBLOCK_WORKBENCH", displayName = text("Multiblock Workbench"), - customModel = "tool/multiblock_workbench" + customModel = "misc/multiblock_workbench" ) { CustomBlocks.MULTIBLOCK_WORKBENCH }) val WRENCH = register(Wrench) val ADVANCED_ITEM_EXTRACTOR = customBlockItem("ADVANCED_ITEM_EXTRACTOR", "misc/advanced_item_extractor", text("Advanced Item Extractor"), CustomBlocks::ADVANCED_ITEM_EXTRACTOR) - val ITEM_FILTER = customBlockItem("ITEM_FILTER", "tool/multiblock_workbench", text("Item Filter"), CustomBlocks::ITEM_FILTER) + val ITEM_FILTER = customBlockItem("ITEM_FILTER", "misc/item_filter", text("Item Filter"), CustomBlocks::ITEM_FILTER) private fun formatToolName(tierName: String, tierColor: TextColor, toolName: String) = ofChildren( text("$tierName ", tierColor), From d3df041adad8e59b1481c1cffdd791c9d9f0da34 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 4 Feb 2025 10:18:08 -0600 Subject: [PATCH 486/500] Store settings --- .../multiblock/MultiblockRegistration.kt | 4 +- .../AbstractShipFactoryMultiblock.kt | 18 +++++ .../AdvancedShipFactoryMultiblock.kt | 47 ++----------- .../type/shipfactory/ShipFactoryEntity.kt | 70 +++++++++++++++++++ .../ShipFactoryMultiblock.kt | 25 +++++-- .../type/shipfactory/ShipFactorySettings.kt | 57 +++++++++++++++ .../starship/factory/StarshipFactories.kt | 5 +- .../persistence/NamespacedKeys.kt | 6 ++ 8 files changed, 179 insertions(+), 53 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AbstractShipFactoryMultiblock.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{misc => shipfactory}/AdvancedShipFactoryMultiblock.kt (72%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactoryEntity.kt rename server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/{misc => shipfactory}/ShipFactoryMultiblock.kt (69%) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactorySettings.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt index fd54f4f787..68aacd25e3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/MultiblockRegistration.kt @@ -40,7 +40,6 @@ import net.horizonsend.ion.server.features.multiblock.type.industry.CompressorMu import net.horizonsend.ion.server.features.multiblock.type.industry.FabricatorMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.GasFurnaceMultiblock import net.horizonsend.ion.server.features.multiblock.type.industry.PlatePressMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.AdvancedShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.AirlockMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.CryoPodMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.DecomposerMultiblock @@ -53,7 +52,6 @@ import net.horizonsend.ion.server.features.multiblock.type.misc.LargeTractorBeam import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.MagazineMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.misc.MobDefender -import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.misc.TractorBeamMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.BoxShieldMultiblock import net.horizonsend.ion.server.features.multiblock.type.particleshield.EventShieldMultiblock @@ -86,6 +84,8 @@ import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterM import net.horizonsend.ion.server.features.multiblock.type.printer.GlassPrinterMultiblockMirrored import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblock import net.horizonsend.ion.server.features.multiblock.type.printer.TechnicalPrinterMultiblockMirrored +import net.horizonsend.ion.server.features.multiblock.type.shipfactory.AdvancedShipFactoryMultiblock +import net.horizonsend.ion.server.features.multiblock.type.shipfactory.ShipFactoryMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.LandingGearMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.OdometerMultiblock import net.horizonsend.ion.server.features.multiblock.type.starship.checklist.BargeReactorMultiBlock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AbstractShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AbstractShipFactoryMultiblock.kt new file mode 100644 index 0000000000..ce5a1faf11 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AbstractShipFactoryMultiblock.kt @@ -0,0 +1,18 @@ +package net.horizonsend.ion.server.features.multiblock.type.shipfactory + +import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock +import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock +import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import org.bukkit.block.Sign +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent + +abstract class AbstractShipFactoryMultiblock : Multiblock(), InteractableMultiblock, DisplayNameMultilblock, EntityMultiblock { + override val name: String = "shipfactory" + + override fun onSignInteract(sign: Sign, player: Player, event: PlayerInteractEvent) { + val entity = AdvancedShipFactoryMultiblock.getMultiblockEntity(sign) ?: return + entity.openMenu(player) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt similarity index 72% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt index 88a71b3bac..b3b0a36a95 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/AdvancedShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt @@ -1,26 +1,15 @@ -package net.horizonsend.ion.server.features.multiblock.type.misc +package net.horizonsend.ion.server.features.multiblock.type.shipfactory import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule -import net.horizonsend.ion.server.features.multiblock.Multiblock -import net.horizonsend.ion.server.features.multiblock.entity.MultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData -import net.horizonsend.ion.server.features.multiblock.entity.type.DisplayMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.StatusMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.UserManagedMultiblockEntity import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.StatusTickedMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.SyncTickingMultiblockEntity -import net.horizonsend.ion.server.features.multiblock.entity.type.ticked.TickedMultiblockEntityParent import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock -import net.horizonsend.ion.server.features.multiblock.type.EntityMultiblock -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock -import net.horizonsend.ion.server.features.multiblock.type.misc.AdvancedShipFactoryMultiblock.AdvancedShipFactoryEntity +import net.horizonsend.ion.server.features.multiblock.type.shipfactory.AdvancedShipFactoryMultiblock.AdvancedShipFactoryEntity import net.horizonsend.ion.server.features.multiblock.util.PrepackagedPreset import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode @@ -37,17 +26,12 @@ import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Material import org.bukkit.World import org.bukkit.block.BlockFace -import org.bukkit.block.Sign import org.bukkit.block.data.Bisected import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT -import org.bukkit.entity.Player -import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext -object AdvancedShipFactoryMultiblock : Multiblock(), EntityMultiblock, DisplayNameMultilblock, InteractableMultiblock { - override val name: String = "shipfactory" - +object AdvancedShipFactoryMultiblock : AbstractShipFactoryMultiblock() { override val signText = createSignText( line1 = text("Starship Factory", NamedTextColor.BLUE), line2 = text("Advanced", NamedTextColor.YELLOW), @@ -109,11 +93,6 @@ object AdvancedShipFactoryMultiblock : Multiblock(), EntityMultiblock, + manager: MultiblockManager, + world: World, + x: Int, + y: Int, + z: Int, + structureDirection: BlockFace +) : MultiblockEntity( + manager, + multiblock, + world, + x, + y, + z, + structureDirection +), StatusTickedMultiblockEntity, SyncTickingMultiblockEntity, UserManagedMultiblockEntity, DisplayMultiblockEntity { + val settings = ShipFactorySettings.load(data) + + override val userManager: UserManagedMultiblockEntity.UserManager = UserManagedMultiblockEntity.UserManager(data, true) + override val tickingManager: TickedMultiblockEntityParent.TickingManager = TickedMultiblockEntityParent.TickingManager(5) + override val statusManager: StatusMultiblockEntity.StatusManager = StatusMultiblockEntity.StatusManager() + + protected companion object { + fun Rotation.displayName(): Component = when (this) { + Rotation.NONE -> Component.text("None") + Rotation.CLOCKWISE_90 -> Component.text("Clockwise 90") + Rotation.CLOCKWISE_180 -> Component.text("Clockwise 180") + Rotation.COUNTERCLOCKWISE_90 -> Component.text("Counter Clockwise 90") + } + } + + fun openMenu(player: Player) { + if (userManager.currentlyUsed()) { + userManager.clear() + return + } + + userManager.setUser(player) + } + + override fun tick() { + if (!userManager.currentlyUsed()) return + println("Toggled on") + } + + override fun storeAdditionalData(store: PersistentMultiblockData, adapterContext: PersistentDataAdapterContext) { + userManager.saveUserData(store) + settings.save(store) + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactoryMultiblock.kt similarity index 69% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactoryMultiblock.kt index 9bf443a05a..0fdf19390a 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/misc/ShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactoryMultiblock.kt @@ -1,15 +1,17 @@ -package net.horizonsend.ion.server.features.multiblock.type.misc +package net.horizonsend.ion.server.features.multiblock.type.shipfactory -import net.horizonsend.ion.server.features.multiblock.Multiblock +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.features.multiblock.manager.MultiblockManager import net.horizonsend.ion.server.features.multiblock.shape.MultiblockShape -import net.horizonsend.ion.server.features.multiblock.type.DisplayNameMultilblock -import net.horizonsend.ion.server.features.multiblock.type.InteractableMultiblock +import net.horizonsend.ion.server.features.multiblock.type.shipfactory.AdvancedShipFactoryMultiblock.AdvancedShipFactoryEntity import net.horizonsend.ion.server.features.starship.factory.StarshipFactories import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.getFacing import net.horizonsend.ion.server.miscellaneous.utils.rightFace import net.kyori.adventure.text.Component import net.kyori.adventure.text.Component.text +import org.bukkit.World +import org.bukkit.block.BlockFace import org.bukkit.block.Sign import org.bukkit.entity.Player import org.bukkit.event.block.Action @@ -17,8 +19,7 @@ import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder -object ShipFactoryMultiblock : Multiblock(), InteractableMultiblock, DisplayNameMultilblock { - override val name = "shipfactory" +object ShipFactoryMultiblock : AbstractShipFactoryMultiblock() { override val signText = createSignText( line1 = "&1Ship Factory", @@ -63,4 +64,16 @@ object ShipFactoryMultiblock : Multiblock(), InteractableMultiblock, DisplayName StarshipFactories.process(event.player, sign, leftClick) } } + + override fun createEntity( + manager: MultiblockManager, + data: PersistentMultiblockData, + world: World, + x: Int, + y: Int, + z: Int, + structureDirection: BlockFace, + ): AdvancedShipFactoryEntity { + return AdvancedShipFactoryEntity(data, manager, x, y, z, world, structureDirection) + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactorySettings.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactorySettings.kt new file mode 100644 index 0000000000..0170d93d6b --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/ShipFactorySettings.kt @@ -0,0 +1,57 @@ +package net.horizonsend.ion.server.features.multiblock.type.shipfactory + +import com.manya.pdc.base.EnumDataType +import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.COMPLETE_OBSTRUCTIONS +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.FLUID_PACEMENT +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.GRAB_NETWORKED_INVENTORIES +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.LEAVE_ITEM_REMAINING +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.ROTATION +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.X +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Y +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys.Z +import net.minecraft.world.level.block.Rotation +import org.bukkit.persistence.PersistentDataType.BOOLEAN +import org.bukkit.persistence.PersistentDataType.INTEGER + +data class ShipFactorySettings( + var offsetX: Int, + var offsetY: Int, + var offsetZ: Int, + var rotation: Rotation, + var placeInFluids: Boolean, + var markObstrcutedBlocksAsComplete: Boolean, + var leaveItemRemaining: Boolean, + var grabFromNetworkedPipes: Boolean +) { + companion object { + private val enumType = EnumDataType(Rotation::class.java) + + fun load(data: PersistentMultiblockData): ShipFactorySettings { + val shipFactorySettings = ShipFactorySettings( + offsetX = data.getAdditionalDataOrDefault(X, INTEGER, 0), + offsetY = data.getAdditionalDataOrDefault(Y, INTEGER, 0), + offsetZ = data.getAdditionalDataOrDefault(Z, INTEGER, 0), + rotation = data.getAdditionalDataOrDefault(ROTATION, enumType, Rotation.NONE), + placeInFluids = data.getAdditionalDataOrDefault(FLUID_PACEMENT, BOOLEAN, false), + markObstrcutedBlocksAsComplete = data.getAdditionalDataOrDefault(COMPLETE_OBSTRUCTIONS, BOOLEAN, true), + leaveItemRemaining = data.getAdditionalDataOrDefault(LEAVE_ITEM_REMAINING, BOOLEAN, false), + grabFromNetworkedPipes = data.getAdditionalDataOrDefault(GRAB_NETWORKED_INVENTORIES, BOOLEAN, false), + ) + + return shipFactorySettings + } + } + + fun save(store: PersistentMultiblockData) { + store.addAdditionalData(X, INTEGER, offsetX) + store.addAdditionalData(Y, INTEGER, offsetY) + store.addAdditionalData(Z, INTEGER, offsetZ) + store.addAdditionalData(ROTATION, enumType, rotation) + store.addAdditionalData(FLUID_PACEMENT, BOOLEAN, placeInFluids) + store.addAdditionalData(COMPLETE_OBSTRUCTIONS, BOOLEAN, markObstrcutedBlocksAsComplete) + store.addAdditionalData(LEAVE_ITEM_REMAINING, BOOLEAN, leaveItemRemaining) + store.addAdditionalData(GRAB_NETWORKED_INVENTORIES, BOOLEAN, grabFromNetworkedPipes) + } +} + diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt index 3076c599f0..0072415fb3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/factory/StarshipFactories.kt @@ -13,7 +13,7 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.toComponent import net.horizonsend.ion.server.IonServerComponent import net.horizonsend.ion.server.features.economy.bazaar.Merchants -import net.horizonsend.ion.server.features.multiblock.type.misc.ShipFactoryMultiblock +import net.horizonsend.ion.server.features.multiblock.type.shipfactory.ShipFactoryMultiblock import net.horizonsend.ion.server.features.player.CombatTimer import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.canAccess @@ -47,9 +47,6 @@ import java.util.Collections.synchronizedMap import java.util.LinkedList import java.util.UUID import java.util.concurrent.TimeUnit -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set import kotlin.math.roundToInt object StarshipFactories : IonServerComponent() { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt index 7e89cf6907..653926f481 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/miscellaneous/registrations/persistence/NamespacedKeys.kt @@ -13,6 +13,7 @@ object NamespacedKeys { val BLOCK_KEY = key("block_key") val AXIS = key("axis") + val ROTATION = key("rotation") val UP_DOWN = key("up_down") val LEFT_RIGHT = key("left_right") @@ -122,6 +123,11 @@ object NamespacedKeys { val TANK_2 = key("tank_2") val TANK_3 = key("tank_3") + val FLUID_PACEMENT = key("fluid_pacement") + val COMPLETE_OBSTRUCTIONS = key("complete_obstructions") + val LEAVE_ITEM_REMAINING = key("leave_item_remaining") + val GRAB_NETWORKED_INVENTORIES = key("grab_networked_inventories") + fun key(key: String) = NamespacedKey(IonServer, key) // Used for datapacks and resource packs From ec3c95bfc38e37bb86e963d1ca60474428d02f64 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:52:43 -0600 Subject: [PATCH 487/500] Synchronize ionchunk access --- .../ion/server/features/world/IonWorld.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt index d5fb4685ca..2caf326312 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/world/IonWorld.kt @@ -4,8 +4,8 @@ import com.destroystokyo.paper.event.server.ServerTickStartEvent import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap import it.unimi.dsi.fastutil.longs.LongOpenHashSet import net.horizonsend.ion.common.utils.configuration.Configuration -import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.IonServerComponent +import net.horizonsend.ion.server.configuration.ConfigurationFiles import net.horizonsend.ion.server.features.multiblock.manager.WorldMultiblockManager import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.inputs.WorldInputManager @@ -39,6 +39,11 @@ class IonWorld private constructor( field = value } + val multiblockManager = WorldMultiblockManager(this) + val inputManager = WorldInputManager(this) + + private val chunkLock = Any() + /** * Key: The location of the chunk packed into a long * @@ -46,43 +51,40 @@ class IonWorld private constructor( **/ private val chunks: Long2ObjectOpenHashMap = Long2ObjectOpenHashMap() - val multiblockManager = WorldMultiblockManager(this) - val inputManager = WorldInputManager(this) - /** * Gets the IonChunk at the specified coordinates if it is loaded **/ fun getChunk(x: Int, z: Int): IonChunk? { val key = Chunk.getChunkKey(x, z) - return chunks[key] + return synchronized(chunkLock) { chunks[key] } } /** * Gets the IonChunk at the specified key if it is loaded **/ fun getChunk(key: Long): IonChunk? { - return chunks[key] + return synchronized(chunkLock) { chunks[key] } } - fun isChunkLoaded(key: Long) = chunks.keys.contains(key) + fun isChunkLoaded(key: Long) = synchronized(chunkLock) { chunks.keys.contains(key) } /** * Adds the chunk **/ fun addChunk(chunk: IonChunk) { - if (chunks.containsKey(chunk.locationKey)) { + if (isChunkLoaded(chunk.locationKey)) { log.warn("Attempted to add a chunk that was already in the map!") } - chunks[chunk.locationKey] = chunk + synchronized(chunkLock) { chunks[chunk.locationKey] = chunk } } /** * Removes the chunk ***/ fun removeChunk(chunk: Chunk): IonChunk? { - val result = chunks.remove(chunk.chunkKey) + val result = synchronized(chunkLock) { chunks.remove(chunk.chunkKey) } if (result == null) { log.warn("Chunk removed that was not in the map!") From 837766ee0860c1d7e322662bd7f9487b70c46866 Mon Sep 17 00:00:00 2001 From: kwazedilla Date: Wed, 5 Feb 2025 00:42:29 -0800 Subject: [PATCH 488/500] advanced ship factory gui initial background --- .../ion/common/utils/text/ComponentUtils.kt | 1 + .../AdvancedShipFactoryMultiblock.kt | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt index 75dd43459c..e17e33b464 100644 --- a/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt +++ b/common/src/main/kotlin/net/horizonsend/ion/common/utils/text/ComponentUtils.kt @@ -147,6 +147,7 @@ const val SPACE_STARRY_BACKGROUND_CHARACTER = '\uF8F7' const val SPACE_MAIN_HYPERSPACE_ROUTES_CHARACTER = '\uF8F6' const val SPACE_MINOR_HYPERSPACE_ROUTES_CHARACTER = '\uF8F5' const val MULTIBLOCK_WORKBENCH = '\uF8F4' +const val ADVANCED_SHIP_FACTORY_CHARACTER = '\uF8F3' // Custom characters end diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt index b3b0a36a95..4016d93e96 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt @@ -1,9 +1,14 @@ package net.horizonsend.ion.server.features.multiblock.type.shipfactory +import net.horizonsend.ion.common.utils.text.ADVANCED_SHIP_FACTORY_CHARACTER import net.horizonsend.ion.server.features.client.display.modular.DisplayHandlers import net.horizonsend.ion.server.features.client.display.modular.TextDisplayHandler import net.horizonsend.ion.server.features.client.display.modular.display.PowerEntityDisplayModule import net.horizonsend.ion.server.features.client.display.modular.display.StatusDisplayModule +import net.horizonsend.ion.server.features.gui.GuiItem +import net.horizonsend.ion.server.features.gui.GuiItems +import net.horizonsend.ion.server.features.gui.GuiText +import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.multiblock.entity.PersistentMultiblockData import net.horizonsend.ion.server.features.multiblock.entity.type.power.PowerStorage import net.horizonsend.ion.server.features.multiblock.entity.type.power.PoweredMultiblockEntity @@ -25,11 +30,18 @@ import net.kyori.adventure.text.Component.text import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.Material import org.bukkit.World +import org.bukkit.block.Block import org.bukkit.block.BlockFace +import org.bukkit.block.Sign import org.bukkit.block.data.Bisected import org.bukkit.block.data.type.Stairs.Shape.STRAIGHT +import org.bukkit.entity.Player +import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataAdapterContext +import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper +import xyz.xenondevs.invui.gui.Gui +import xyz.xenondevs.invui.window.Window object AdvancedShipFactoryMultiblock : AbstractShipFactoryMultiblock() { override val signText = createSignText( @@ -105,6 +117,10 @@ object AdvancedShipFactoryMultiblock : AbstractShipFactoryMultiblock Date: Wed, 5 Feb 2025 11:14:41 -0600 Subject: [PATCH 489/500] organize a little --- .../features/custom/blocks/CustomBlockListeners.kt | 1 + .../server/features/custom/blocks/CustomBlocks.kt | 1 + .../custom/blocks/extractor/CustomExtractorBlock.kt | 4 ++-- .../custom/blocks/filter/CustomFilterBlock.kt | 4 ++-- .../blocks/{ => misc}/InteractableCustomBlock.kt | 12 +++++++----- .../custom/blocks/{ => misc}/MultiblockWorkbench.kt | 4 +++- .../custom/blocks/{ => misc}/WrenchRemovable.kt | 2 +- .../ion/server/features/custom/items/misc/Wrench.kt | 2 +- 8 files changed, 18 insertions(+), 12 deletions(-) rename server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/{ => misc}/InteractableCustomBlock.kt (59%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/{ => misc}/MultiblockWorkbench.kt (98%) rename server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/{ => misc}/WrenchRemovable.kt (70%) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt index e5b67d9527..9264f1a869 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt @@ -2,6 +2,7 @@ package net.horizonsend.ion.server.features.custom.blocks import io.papermc.paper.event.player.PlayerPickItemEvent import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock +import net.horizonsend.ion.server.features.custom.blocks.misc.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.listener.SLEventListener diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 4f29194b90..5b616e0a8f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.custom.blocks import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import net.horizonsend.ion.server.features.custom.blocks.extractor.AdvancedItemExtractorBlock import net.horizonsend.ion.server.features.custom.blocks.filter.ItemFilterBlock +import net.horizonsend.ion.server.features.custom.blocks.misc.MultiblockWorkbench import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.POWER_DRILL_BASIC diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index 9f2d71c8a2..ed70cdeed9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.custom.blocks.extractor import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.orEmpty import net.horizonsend.ion.server.features.custom.blocks.BlockLoot -import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock -import net.horizonsend.ion.server.features.custom.blocks.WrenchRemovable +import net.horizonsend.ion.server.features.custom.blocks.misc.InteractableCustomBlock +import net.horizonsend.ion.server.features.custom.blocks.misc.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorData import net.horizonsend.ion.server.features.transport.manager.extractors.data.ExtractorMetaData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt index 412aecfd0a..6dd62c3b43 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -3,8 +3,8 @@ package net.horizonsend.ion.server.features.custom.blocks.filter import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.orEmpty import net.horizonsend.ion.server.features.custom.blocks.BlockLoot -import net.horizonsend.ion.server.features.custom.blocks.InteractableCustomBlock -import net.horizonsend.ion.server.features.custom.blocks.WrenchRemovable +import net.horizonsend.ion.server.features.custom.blocks.misc.InteractableCustomBlock +import net.horizonsend.ion.server.features.custom.blocks.misc.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.transport.filters.FilterData diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt similarity index 59% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt index 31a202f6a7..3c8c7d8270 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/InteractableCustomBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt @@ -1,5 +1,7 @@ -package net.horizonsend.ion.server.features.custom.blocks +package net.horizonsend.ion.server.features.custom.blocks.misc +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import org.bukkit.block.Block import org.bukkit.block.data.BlockData @@ -7,10 +9,10 @@ import org.bukkit.event.player.PlayerInteractEvent import java.util.function.Supplier abstract class InteractableCustomBlock( - identifier: String, - blockData: BlockData, - drops: BlockLoot, - customBlockItem: Supplier + identifier: String, + blockData: BlockData, + drops: BlockLoot, + customBlockItem: Supplier ) : CustomBlock(identifier, blockData, drops, customBlockItem) { open fun onRightClick(event: PlayerInteractEvent, block: Block) {} open fun onLeftClick(event: PlayerInteractEvent, block: Block) {} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt similarity index 98% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt index 8bc842547e..c03f8286d6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.custom.blocks +package net.horizonsend.ion.server.features.custom.blocks.misc import io.papermc.paper.datacomponent.DataComponentTypes import net.horizonsend.ion.common.utils.text.DEFAULT_GUI_WIDTH @@ -6,6 +6,8 @@ import net.horizonsend.ion.common.utils.text.MULTIBLOCK_WORKBENCH import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.IonServer +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.gui.GuiItem diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/WrenchRemovable.kt similarity index 70% rename from server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt rename to server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/WrenchRemovable.kt index e4448f541e..9caffe57cb 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/WrenchRemovable.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/WrenchRemovable.kt @@ -1,4 +1,4 @@ -package net.horizonsend.ion.server.features.custom.blocks +package net.horizonsend.ion.server.features.custom.blocks.misc import org.bukkit.block.Block import org.bukkit.inventory.ItemStack diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt index bbd6ec3da3..bb0af16b3f 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/items/misc/Wrench.kt @@ -5,7 +5,7 @@ import net.horizonsend.ion.server.command.misc.MultiblockCommand import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlockListeners import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks -import net.horizonsend.ion.server.features.custom.blocks.WrenchRemovable +import net.horizonsend.ion.server.features.custom.blocks.misc.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.component.CustomComponentTypes import net.horizonsend.ion.server.features.custom.items.component.CustomItemComponentManager From 9bb13836858c8e95f2e89d1cca3ebad0673f7eee Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:03:22 -0600 Subject: [PATCH 490/500] add directional custom blocks --- .../features/custom/blocks/CustomBlocks.kt | 15 ++++++++++ .../blocks/extractor/CustomExtractorBlock.kt | 3 +- .../custom/blocks/filter/CustomFilterBlock.kt | 28 ++++--------------- .../custom/blocks/filter/ItemFilterBlock.kt | 16 +++++++++-- .../blocks/misc/DirectionalCustomBlock.kt | 21 ++++++++++++++ .../blocks/misc/InteractableCustomBlock.kt | 16 ++--------- .../custom/blocks/misc/MultiblockWorkbench.kt | 5 ++-- 7 files changed, 64 insertions(+), 40 deletions(-) create mode 100644 server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/DirectionalCustomBlock.kt diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 5b616e0a8f..8383f7bcaa 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -1,8 +1,10 @@ package net.horizonsend.ion.server.features.custom.blocks +import com.google.common.collect.HashBasedTable import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import net.horizonsend.ion.server.features.custom.blocks.extractor.AdvancedItemExtractorBlock import net.horizonsend.ion.server.features.custom.blocks.filter.ItemFilterBlock +import net.horizonsend.ion.server.features.custom.blocks.misc.DirectionalCustomBlock import net.horizonsend.ion.server.features.custom.blocks.misc.MultiblockWorkbench import net.horizonsend.ion.server.features.custom.items.CustomItem import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry @@ -12,6 +14,7 @@ import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.miscellaneous.utils.getMatchingMaterials import net.horizonsend.ion.server.miscellaneous.utils.map import net.horizonsend.ion.server.miscellaneous.utils.nms +import net.horizonsend.ion.server.miscellaneous.utils.set import net.minecraft.world.level.block.state.BlockState import org.bukkit.Material import org.bukkit.block.Block @@ -31,6 +34,7 @@ object CustomBlocks { val ALL get() = customBlocks.values private val customBlocks: MutableMap = mutableMapOf() private val customBlocksData = Object2ObjectOpenHashMap() + private val directionalCustomBlocksData = HashBasedTable.create() fun mushroomBlockData(faces: Set) : BlockData { return Material.BROWN_MUSHROOM_BLOCK.createBlockData { data -> @@ -224,6 +228,17 @@ object CustomBlocks { return customBlock } + fun registerDirectional(customBlock: T): T { + customBlocks[customBlock.identifier] = customBlock + customBlocksData[customBlock.blockData.nms] = customBlock + + for ((data, face) in customBlock.faceLookup) { + directionalCustomBlocksData[data.nms, face] = customBlock + } + + return customBlock + } + val identifiers = customBlocks.keys val Block.customBlock get(): CustomBlock? = getByBlock(this) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt index ed70cdeed9..dd2f97390d 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/CustomExtractorBlock.kt @@ -3,6 +3,7 @@ package net.horizonsend.ion.server.features.custom.blocks.extractor import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.orEmpty import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.misc.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.blocks.misc.WrenchRemovable import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem @@ -34,7 +35,7 @@ abstract class CustomExtractorBlock( drops: BlockLoot, customBlockItem: Supplier, val extractorDataType: KClass -) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem), WrenchRemovable { +) : CustomBlock(identifier, blockData, drops, customBlockItem), InteractableCustomBlock, WrenchRemovable { val cooldown = PerPlayerCooldown(5L) fun load(key: BlockKey, container: MetaDataContainer<*, *>): T { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt index 6dd62c3b43..fbfdaa89f3 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/CustomFilterBlock.kt @@ -2,10 +2,8 @@ package net.horizonsend.ion.server.features.custom.blocks.filter import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.orEmpty -import net.horizonsend.ion.server.features.custom.blocks.BlockLoot import net.horizonsend.ion.server.features.custom.blocks.misc.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.blocks.misc.WrenchRemovable -import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta @@ -21,19 +19,15 @@ import net.horizonsend.ion.server.miscellaneous.utils.updatePersistentDataContai import net.kyori.adventure.text.Component import org.bukkit.block.Block import org.bukkit.block.TileState -import org.bukkit.block.data.BlockData import org.bukkit.entity.Player import org.bukkit.event.player.PlayerInteractEvent import org.bukkit.inventory.ItemStack import java.util.function.Supplier -abstract class CustomFilterBlock( - identifier: String, - blockData: BlockData, - drops: BlockLoot, - customBlockItem: Supplier -) : InteractableCustomBlock(identifier, blockData, drops, customBlockItem), WrenchRemovable { - val cooldown = PerPlayerCooldown(5L) +interface CustomFilterBlock : WrenchRemovable, InteractableCustomBlock { + companion object { + val cooldown = PerPlayerCooldown(5L) + } override fun onRightClick(event: PlayerInteractEvent, block: Block) { if (event.player.isSneaking) return @@ -57,9 +51,9 @@ abstract class CustomFilterBlock( } } - abstract fun createData(pos: BlockKey): FilterData + fun createData(pos: BlockKey): FilterData - abstract fun getGui(player: Player, block: Block, filterData: FilterData, tileState: Supplier) : GuiWrapper + fun getGui(player: Player, block: Block, filterData: FilterData, tileState: Supplier) : GuiWrapper override fun decorateItem(itemStack: ItemStack, block: Block) { val state = block.state @@ -75,14 +69,4 @@ abstract class CustomFilterBlock( set(NamespacedKeys.FILTER_DATA, FilterData, data) } } - - override fun placeCallback(placedItem: ItemStack, block: Block) { - val storedFilterData = placedItem.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return - - val state = block.state - if (state !is TileState) return - - state.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, storedFilterData) - state.update() - } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index d94d503cce..80e2382c5c 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.custom.blocks.filter import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.gui.GuiWrapper @@ -8,6 +9,7 @@ import net.horizonsend.ion.server.features.gui.custom.filter.ItemFilterGui import net.horizonsend.ion.server.features.transport.filters.FilterData import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType +import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import org.bukkit.Axis import org.bukkit.Material @@ -18,7 +20,7 @@ import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import java.util.function.Supplier -object ItemFilterBlock : CustomFilterBlock( +object ItemFilterBlock : CustomBlock( identifier = "ITEM_FILTER", blockData = Material.CREAKING_HEART.createBlockData { t -> t as CreakingHeart @@ -31,7 +33,7 @@ object ItemFilterBlock : CustomFilterBlock( drops = customItemDrop(CustomItemRegistry::ITEM_FILTER) ), customBlockItem = CustomItemRegistry::ITEM_FILTER, -) { +), CustomFilterBlock { override fun createData(pos: BlockKey): FilterData { return FilterData(pos, FilterType.ItemType) } @@ -44,4 +46,14 @@ object ItemFilterBlock : CustomFilterBlock( ): GuiWrapper { return ItemFilterGui(player, filterData, tileState) } + + override fun placeCallback(placedItem: ItemStack, block: Block) { + val storedFilterData = placedItem.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return + + val state = block.state + if (state !is TileState) return + + state.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, storedFilterData) + state.update() + } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/DirectionalCustomBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/DirectionalCustomBlock.kt new file mode 100644 index 0000000000..64ae838376 --- /dev/null +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/DirectionalCustomBlock.kt @@ -0,0 +1,21 @@ +package net.horizonsend.ion.server.features.custom.blocks.misc + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock +import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem +import org.bukkit.block.BlockFace +import org.bukkit.block.data.BlockData +import java.util.function.Supplier + +abstract class DirectionalCustomBlock( + identifier: String, + val faceData: Map, + drops: BlockLoot, + customBlockItem: Supplier +) : CustomBlock(identifier, faceData[BlockFace.NORTH]!!, drops, customBlockItem) { + val faceLookup = faceData.entries.associateTo(Object2ObjectOpenHashMap()) { entry -> entry.value to entry.key } + fun getFace(data: BlockData): BlockFace { + return faceLookup[data] ?: throw NoSuchElementException("Face for $data does not exist") + } +} diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt index 3c8c7d8270..f82346bfde 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/InteractableCustomBlock.kt @@ -1,19 +1,9 @@ package net.horizonsend.ion.server.features.custom.blocks.misc -import net.horizonsend.ion.server.features.custom.blocks.BlockLoot -import net.horizonsend.ion.server.features.custom.blocks.CustomBlock -import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import org.bukkit.block.Block -import org.bukkit.block.data.BlockData import org.bukkit.event.player.PlayerInteractEvent -import java.util.function.Supplier -abstract class InteractableCustomBlock( - identifier: String, - blockData: BlockData, - drops: BlockLoot, - customBlockItem: Supplier -) : CustomBlock(identifier, blockData, drops, customBlockItem) { - open fun onRightClick(event: PlayerInteractEvent, block: Block) {} - open fun onLeftClick(event: PlayerInteractEvent, block: Block) {} +interface InteractableCustomBlock { + fun onRightClick(event: PlayerInteractEvent, block: Block) {} + fun onLeftClick(event: PlayerInteractEvent, block: Block) {} } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt index c03f8286d6..b8b58065bf 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/misc/MultiblockWorkbench.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.common.utils.text.ofChildren import net.horizonsend.ion.common.utils.text.wrap import net.horizonsend.ion.server.IonServer import net.horizonsend.ion.server.features.custom.blocks.BlockLoot +import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry @@ -49,7 +50,7 @@ import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack import java.util.concurrent.TimeUnit -object MultiblockWorkbench : InteractableCustomBlock( +object MultiblockWorkbench : CustomBlock( identifier = "MULTIBLOCK_WORKBENCH", blockData = CustomBlocks.mushroomBlockData(setOf(BlockFace.NORTH, BlockFace.DOWN, BlockFace.EAST)), drops = BlockLoot( @@ -57,7 +58,7 @@ object MultiblockWorkbench : InteractableCustomBlock( drops = customItemDrop("MULTIBLOCK_WORKBENCH", 1) ), customBlockItem = { CustomItemRegistry.MULTIBLOCK_WORKBENCH } -) { +), InteractableCustomBlock { private val cooldown = PerPlayerCooldown(5L, TimeUnit.MILLISECONDS) // Initalized before multiblocks are registered From 3696cebeb844a2139345b8c108d82a659131035f Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:21:19 -0600 Subject: [PATCH 491/500] convert new custom blocks to vaults, disable vault mechanics --- server/build.gradle.kts | 2 +- .../extractor/AdvancedItemExtractorBlock.kt | 14 ++--- .../custom/blocks/filter/ItemFilterBlock.kt | 61 +++++++++++++++---- .../server/features/starship/FlyableBlocks.kt | 4 +- .../features/transport/util/CacheType.kt | 7 +-- .../server/listener/fixers/CancelListeners.kt | 49 +++++++++++++-- 6 files changed, 106 insertions(+), 31 deletions(-) diff --git a/server/build.gradle.kts b/server/build.gradle.kts index 4714110462..94f3b4fdc0 100644 --- a/server/build.gradle.kts +++ b/server/build.gradle.kts @@ -6,7 +6,7 @@ plugins { kotlin("plugin.serialization") id("com.github.johnrengelman.shadow") - id("io.papermc.paperweight.userdev") version "2.0.0-beta.11" + id("io.papermc.paperweight.userdev") version "2.0.0-beta.14" } repositories { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt index 62ec1a4781..0ea5f0fd7b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/extractor/AdvancedItemExtractorBlock.kt @@ -16,11 +16,11 @@ import net.horizonsend.ion.server.miscellaneous.registrations.persistence.Namesp import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block +import org.bukkit.block.BlockFace import org.bukkit.block.TileState -import org.bukkit.block.data.type.CreakingHeart +import org.bukkit.block.data.type.Vault import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import xyz.xenondevs.inventoryaccess.component.AdventureComponentWrapper @@ -30,11 +30,11 @@ import xyz.xenondevs.invui.window.Window object AdvancedItemExtractorBlock : CustomExtractorBlock( "ADVANCED_ITEM_EXTRACTOR", - blockData = Material.CREAKING_HEART.createBlockData { t -> - t as CreakingHeart - t.axis = Axis.X - t.isNatural = false - t.isActive = false + blockData = Material.VAULT.createBlockData { t -> + t as Vault + t.facing = BlockFace.SOUTH + t.isOminous = false + t.vaultState = Vault.State.INACTIVE }, BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index 80e2382c5c..59bb247d21 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -1,8 +1,8 @@ package net.horizonsend.ion.server.features.custom.blocks.filter import net.horizonsend.ion.server.features.custom.blocks.BlockLoot -import net.horizonsend.ion.server.features.custom.blocks.CustomBlock import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customItemDrop +import net.horizonsend.ion.server.features.custom.blocks.misc.DirectionalCustomBlock import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry import net.horizonsend.ion.server.features.gui.GuiWrapper import net.horizonsend.ion.server.features.gui.custom.filter.ItemFilterGui @@ -11,23 +11,57 @@ import net.horizonsend.ion.server.features.transport.filters.FilterMeta.ItemFilt import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey -import org.bukkit.Axis import org.bukkit.Material import org.bukkit.block.Block +import org.bukkit.block.BlockFace import org.bukkit.block.TileState -import org.bukkit.block.data.type.CreakingHeart +import org.bukkit.block.Vault as VaultState +import org.bukkit.block.data.type.Vault as VaultData +import org.bukkit.craftbukkit.block.CraftVault import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import java.util.function.Supplier -object ItemFilterBlock : CustomBlock( +object ItemFilterBlock : DirectionalCustomBlock( identifier = "ITEM_FILTER", - blockData = Material.CREAKING_HEART.createBlockData { t -> - t as CreakingHeart - t.axis = Axis.Z - t.isNatural = false - t.isActive = false - }, + faceData = mapOf( + BlockFace.NORTH to Material.VAULT.createBlockData { t -> + t as VaultData + t.facing = BlockFace.NORTH + t.isOminous = true + t.vaultState = VaultData.State.INACTIVE + }, + BlockFace.SOUTH to Material.VAULT.createBlockData { t -> + t as VaultData + t.facing = BlockFace.SOUTH + t.isOminous = true + t.vaultState = VaultData.State.INACTIVE + }, + BlockFace.EAST to Material.VAULT.createBlockData { t -> + t as VaultData + t.facing = BlockFace.EAST + t.isOminous = true + t.vaultState = VaultData.State.INACTIVE + }, + BlockFace.WEST to Material.VAULT.createBlockData { t -> + t as VaultData + t.facing = BlockFace.WEST + t.isOminous = true + t.vaultState = VaultData.State.INACTIVE + }, + BlockFace.UP to Material.VAULT.createBlockData { t -> + t as VaultData + t.facing = BlockFace.NORTH + t.isOminous = true + t.vaultState = VaultData.State.EJECTING + }, + BlockFace.DOWN to Material.VAULT.createBlockData { t -> + t as VaultData + t.facing = BlockFace.NORTH + t.isOminous = true + t.vaultState = VaultData.State.UNLOCKING + } + ), drops = BlockLoot( requiredTool = { BlockLoot.Tool.PICKAXE }, drops = customItemDrop(CustomItemRegistry::ITEM_FILTER) @@ -35,7 +69,7 @@ object ItemFilterBlock : CustomBlock( customBlockItem = CustomItemRegistry::ITEM_FILTER, ), CustomFilterBlock { override fun createData(pos: BlockKey): FilterData { - return FilterData(pos, FilterType.ItemType) + return FilterData(pos, FilterType.ItemType) } override fun getGui( @@ -51,9 +85,12 @@ object ItemFilterBlock : CustomBlock( val storedFilterData = placedItem.persistentDataContainer.get(NamespacedKeys.FILTER_DATA, FilterData) ?: return val state = block.state - if (state !is TileState) return + if (state !is VaultState) return + state as CraftVault state.persistentDataContainer.set(NamespacedKeys.FILTER_DATA, FilterData, storedFilterData) + state.tileEntity.sharedData + state.update() } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt index 47ee53c3f5..4f4d45cabe 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/starship/FlyableBlocks.kt @@ -49,7 +49,6 @@ import org.bukkit.Material.COMPOSTER import org.bukkit.Material.COPPER_BLOCK import org.bukkit.Material.COPPER_GRATE import org.bukkit.Material.CRAFTING_TABLE -import org.bukkit.Material.CREAKING_HEART import org.bukkit.Material.CREEPER_HEAD import org.bukkit.Material.CREEPER_WALL_HEAD import org.bukkit.Material.DAMAGED_ANVIL @@ -160,6 +159,7 @@ import org.bukkit.Material.TARGET import org.bukkit.Material.TERRACOTTA import org.bukkit.Material.TORCH import org.bukkit.Material.TRAPPED_CHEST +import org.bukkit.Material.VAULT import org.bukkit.Material.VERDANT_FROGLIGHT import org.bukkit.Material.WALL_TORCH import org.bukkit.Material.WATER_CAULDRON @@ -208,7 +208,7 @@ val FLYABLE_BLOCKS: EnumSet = mutableSetOf( EMERALD_BLOCK, COAL_BLOCK, BROWN_MUSHROOM_BLOCK, // custom ores - CREAKING_HEART, // custom blocks + VAULT, // custom blocks // used for landing gears PISTON, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index faa12a17fa..7676c99dc8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -15,7 +15,6 @@ import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.SolidG import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerFlowMeter import net.horizonsend.ion.server.features.transport.nodes.types.PowerNode.PowerInputNode -import net.horizonsend.ion.server.features.transport.util.CacheType.entries import net.horizonsend.ion.server.features.world.chunk.IonChunk import net.horizonsend.ion.server.miscellaneous.registrations.persistence.NamespacedKeys import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_PANE_TYPES @@ -41,9 +40,9 @@ import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER import org.bukkit.Material.WAXED_WEATHERED_CHISELED_COPPER import org.bukkit.NamespacedKey -import org.bukkit.block.data.type.CreakingHeart import org.bukkit.block.data.type.Hopper import org.bukkit.block.data.type.Observer +import org.bukkit.block.data.type.Vault import org.bukkit.craftbukkit.block.impl.CraftEndRod import org.bukkit.craftbukkit.block.impl.CraftGrindstone import org.bukkit.craftbukkit.block.impl.CraftLightningRod @@ -112,14 +111,14 @@ enum class CacheType(val namespacedKey: NamespacedKey) { ITEMS(NamespacedKeys.ITEM_TRANSPORT) { override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() .addSimpleNode(CRAFTING_TABLE, ItemNode.ItemExtractorNode) - .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _, _ -> ItemNode.ItemExtractorNode } + .addDataHandler(CustomBlocks.ADVANCED_ITEM_EXTRACTOR) { _, _, _ -> ItemNode.ItemExtractorNode } .addSimpleNode(STAINED_GLASS_TYPES) { _, material, _ -> SolidGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(STAINED_GLASS_PANE_TYPES) { _, material, _ -> ItemNode.PaneGlassNode(ItemNode.PipeChannel[material]!!) } .addSimpleNode(GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(TINTED_GLASS, ItemNode.WildcardSolidGlassNode) .addDataHandler(GRINDSTONE) { data, key, _ -> ItemNode.ItemMergeNode } - .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache) } + .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache) } .addDataHandler(Material.HOPPER) { data, key, holder -> ItemNode.HopperFilterNode(key, data.facing, holder.cache as ItemTransportCache) } .addSimpleNode( Material.CHEST, diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt index e74945c5d2..a143ce998e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/listener/fixers/CancelListeners.kt @@ -8,13 +8,23 @@ import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.listener.SLEventListener +import net.horizonsend.ion.server.miscellaneous.utils.Tasks import net.horizonsend.ion.server.miscellaneous.utils.enumSetOf import net.horizonsend.ion.server.miscellaneous.utils.isBed import net.horizonsend.ion.server.miscellaneous.utils.isShulkerBox +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.entity.Entity import net.minecraft.world.entity.item.ItemEntity +import net.minecraft.world.entity.player.Player +import net.minecraft.world.level.block.Blocks +import net.minecraft.world.level.block.entity.trialspawner.PlayerDetector +import net.minecraft.world.level.block.entity.vault.VaultConfig +import net.minecraft.world.level.block.entity.vault.VaultServerData +import net.minecraft.world.level.entity.EntityTypeTest +import net.minecraft.world.phys.AABB import org.bukkit.Material +import org.bukkit.craftbukkit.block.CraftVault import org.bukkit.entity.EnderPearl -import org.bukkit.entity.EntityType import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority import org.bukkit.event.block.Action @@ -24,7 +34,7 @@ import org.bukkit.event.block.BlockFadeEvent import org.bukkit.event.block.BlockFormEvent import org.bukkit.event.block.BlockPistonExtendEvent import org.bukkit.event.block.BlockPistonRetractEvent -import org.bukkit.event.entity.CreatureSpawnEvent +import org.bukkit.event.block.BlockPlaceEvent import org.bukkit.event.entity.EntityDamageEvent import org.bukkit.event.entity.EntityExplodeEvent import org.bukkit.event.entity.PotionSplashEvent @@ -35,6 +45,9 @@ import org.bukkit.event.player.PlayerItemConsumeEvent import org.bukkit.event.player.PlayerKickEvent import org.bukkit.event.player.PlayerTeleportEvent import org.bukkit.inventory.ItemStack +import java.lang.reflect.Field +import java.util.Optional +import java.util.function.Predicate class CancelListeners : SLEventListener() { private val preventFormBlocks = enumSetOf( @@ -220,8 +233,34 @@ class CancelListeners : SLEventListener() { } } - @EventHandler - fun onMonsterSpawn(event: CreatureSpawnEvent) { - if (event.entity.type == EntityType.CREAKING) event.isCancelled = true + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + fun onTrialVaultPlacement(event: BlockPlaceEvent) { + Tasks.sync { + val state = event.block.state + if (state !is CraftVault) return@sync + + val entity = state.tileEntity + + entity.config = disabledVaultConfig + vaultServerDataResumeField.set(entity.serverData, Long.MAX_VALUE) + } } + + private val vaultServerDataResumeField: Field = VaultServerData::class.java.getDeclaredField("stateUpdatingResumesAt").apply { isAccessible = true } + + private val emptyPlayerDetector = PlayerDetector { _, _, _, _, _ -> listOf() } + private val emptyEntitySelector = object : PlayerDetector.EntitySelector { + override fun getPlayers(p0: ServerLevel, p1: Predicate): List = listOf() + override fun getEntities(p0: ServerLevel, p1: EntityTypeTest, p2: AABB, p3: Predicate): List = listOf() + } + + private val disabledVaultConfig = VaultConfig( + net.minecraft.world.entity.EntityType.BAT.defaultLootTable.get(), + 0.0, + 0.0001, + net.minecraft.world.item.ItemStack(Blocks.BEDROCK), + Optional.empty(), + emptyPlayerDetector, + emptyEntitySelector, + ) } From 2819a00b30800c2a799b0866f634a03ae4ad849d Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:40:36 -0600 Subject: [PATCH 492/500] Allow placement of directional custom blocks --- .../custom/blocks/CustomBlockListeners.kt | 25 ++++++++++++++++++- .../features/custom/blocks/CustomBlocks.kt | 8 +++--- .../custom/blocks/filter/ItemFilterBlock.kt | 6 ++--- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt index 9264f1a869..d2808b479b 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlockListeners.kt @@ -2,15 +2,18 @@ package net.horizonsend.ion.server.features.custom.blocks import io.papermc.paper.event.player.PlayerPickItemEvent import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.customBlock +import net.horizonsend.ion.server.features.custom.blocks.misc.DirectionalCustomBlock import net.horizonsend.ion.server.features.custom.blocks.misc.InteractableCustomBlock import net.horizonsend.ion.server.features.custom.items.CustomItemRegistry.customItem import net.horizonsend.ion.server.features.custom.items.type.CustomBlockItem import net.horizonsend.ion.server.listener.SLEventListener import net.horizonsend.ion.server.miscellaneous.utils.Tasks +import net.horizonsend.ion.server.miscellaneous.utils.coordinates.vectorToBlockFace import net.minecraft.server.network.ServerGamePacketListenerImpl import org.bukkit.GameMode import org.bukkit.Material import org.bukkit.attribute.Attribute +import org.bukkit.block.BlockFace import org.bukkit.enchantments.Enchantment import org.bukkit.event.EventHandler import org.bukkit.event.EventPriority @@ -32,7 +35,27 @@ object CustomBlockListeners : SLEventListener() { val item: CustomBlockItem = itemStack.customItem as? CustomBlockItem ?: return val block = item.getCustomBlock() - event.block.location.block.setBlockData(block.blockData, true) + if (block is DirectionalCustomBlock) { + val faceVertical = vectorToBlockFace(event.player.location.direction, includeVertical = true) + val faceHorizontal = vectorToBlockFace(event.player.location.direction, includeVertical = false) + val placedAgainst = BlockFace.entries.first { + it.modX == (event.blockAgainst.x - event.blockPlaced.x) && + it.modY == (event.blockAgainst.y - event.blockPlaced.y) && + it.modZ == (event.blockAgainst.z - event.blockPlaced.z) + } + + val data = when { + block.faceData.containsKey(faceVertical) -> block.faceData[faceVertical]!! + block.faceData.containsKey(faceHorizontal) -> block.faceData[faceHorizontal]!! + block.faceData.containsKey(placedAgainst) -> block.faceData[placedAgainst]!! + else -> block.blockData + } + + event.block.location.block.setBlockData(data, true) + } else { + event.block.location.block.setBlockData(block.blockData, true) + } + block.placeCallback(itemStack, event.block) } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt index 8383f7bcaa..97cc469703 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/CustomBlocks.kt @@ -34,7 +34,7 @@ object CustomBlocks { val ALL get() = customBlocks.values private val customBlocks: MutableMap = mutableMapOf() private val customBlocksData = Object2ObjectOpenHashMap() - private val directionalCustomBlocksData = HashBasedTable.create() + private val directionalCustomBlocksData = HashBasedTable.create() fun mushroomBlockData(faces: Set) : BlockData { return Material.BROWN_MUSHROOM_BLOCK.createBlockData { data -> @@ -213,7 +213,7 @@ object CustomBlocks { val MULTIBLOCK_WORKBENCH = register(MultiblockWorkbench) val ADVANCED_ITEM_EXTRACTOR = register(AdvancedItemExtractorBlock) - val ITEM_FILTER = register(ItemFilterBlock) + val ITEM_FILTER = registerDirectional(ItemFilterBlock) fun customItemDrop(identifier: String, amount: Int = 1): Supplier> { val customItem = CustomItemRegistry.getByIdentifier(identifier)?.constructItemStack() ?: return Supplier { listOf() } @@ -230,10 +230,10 @@ object CustomBlocks { fun registerDirectional(customBlock: T): T { customBlocks[customBlock.identifier] = customBlock - customBlocksData[customBlock.blockData.nms] = customBlock for ((data, face) in customBlock.faceLookup) { - directionalCustomBlocksData[data.nms, face] = customBlock + directionalCustomBlocksData[data.nms, customBlock] = face + customBlocksData[data.nms] = customBlock } return customBlock diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt index 59bb247d21..e4a1fa7ba6 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/custom/blocks/filter/ItemFilterBlock.kt @@ -52,14 +52,14 @@ object ItemFilterBlock : DirectionalCustomBlock( BlockFace.UP to Material.VAULT.createBlockData { t -> t as VaultData t.facing = BlockFace.NORTH - t.isOminous = true - t.vaultState = VaultData.State.EJECTING + t.isOminous = false + t.vaultState = VaultData.State.ACTIVE }, BlockFace.DOWN to Material.VAULT.createBlockData { t -> t as VaultData t.facing = BlockFace.NORTH t.isOminous = true - t.vaultState = VaultData.State.UNLOCKING + t.vaultState = VaultData.State.ACTIVE } ), drops = BlockLoot( From 69618a3868c467a2982501bee36887361bbc2503 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:49:52 -0600 Subject: [PATCH 493/500] Make item filter node use face --- .../ion/server/features/transport/nodes/types/ItemNode.kt | 7 +------ .../ion/server/features/transport/util/CacheType.kt | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 20124e695a..16d4cc6e90 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -7,7 +7,6 @@ import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache -import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode.PipeChannel.entries import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -99,7 +98,7 @@ interface ItemNode : Node { fun matches(itemStack: ItemStack) : Boolean } - data class AdvancedFilterNode(val position: BlockKey, val cache: ItemTransportCache) : FilterNode { + data class AdvancedFilterNode(val position: BlockKey, val cache: ItemTransportCache, val face: BlockFace) : FilterNode { val filter: WeakReference> = WeakReference(cache.holder.transportManager.filterManager.getFilter(position, FilterType.ItemType)!!) override val pathfindingResistance: Double = 1.0 @@ -112,10 +111,6 @@ interface ItemNode : Node { override fun matches(itemStack: ItemStack): Boolean { return filter.get()?.matchesFilter(itemStack) == true } - - override fun toString(): String { - return filter.get().toString() - } } data class HopperFilterNode(val position: BlockKey, var face: BlockFace, val cache: ItemTransportCache) : FilterNode, ComplexNode { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index 7676c99dc8..100ec3e5f8 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -117,8 +117,8 @@ enum class CacheType(val namespacedKey: NamespacedKey) { .addSimpleNode(GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(TINTED_GLASS, ItemNode.WildcardSolidGlassNode) - .addDataHandler(GRINDSTONE) { data, key, _ -> ItemNode.ItemMergeNode } - .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache) } + .addDataHandler(GRINDSTONE) { _, _, _ -> ItemNode.ItemMergeNode } + .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache, CustomBlocks.ITEM_FILTER.getFace(data)) } .addDataHandler(Material.HOPPER) { data, key, holder -> ItemNode.HopperFilterNode(key, data.facing, holder.cache as ItemTransportCache) } .addSimpleNode( Material.CHEST, From 3c2f04e07b90569bc8ed8e44b76881d5672829fb Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Wed, 5 Feb 2025 18:24:57 -0600 Subject: [PATCH 494/500] closer item pipe configuration --- .../transport/nodes/types/ItemNode.kt | 55 ++++++++++++------- .../features/transport/util/CacheType.kt | 41 ++++++++------ 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 16d4cc6e90..77facb67c5 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -7,6 +7,7 @@ import net.horizonsend.ion.server.features.transport.filters.FilterMeta import net.horizonsend.ion.server.features.transport.filters.FilterType import net.horizonsend.ion.server.features.transport.manager.holders.CacheHolder import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache +import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.old.pipe.filter.FilterItemData import net.horizonsend.ion.server.features.transport.util.CacheType import net.horizonsend.ion.server.miscellaneous.utils.ADJACENT_BLOCK_FACES @@ -48,9 +49,7 @@ interface ItemNode : Node { override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) } - sealed interface IntermediateNode - - sealed interface ChanneledItemNode : IntermediateNode { + sealed interface ChanneledItemNode { val channel: PipeChannel /** @@ -71,25 +70,41 @@ interface ItemNode : Node { } data class PaneGlassNode(override val channel: PipeChannel) : ItemNode, ChanneledItemNode { - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = channelCheck(other) //TODO - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = channelCheck(other) //TODO + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = channelCheck(other) + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = channelCheck(other) + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - override val pathfindingResistance: Double = 1.0 + override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { + val forward = backwards.oppositeFace + + val filtered = mutableListOf() + for (node in nextNodes) { + if (node.offset == forward) filtered.add(node) + if (node.type is InventoryNode) filtered.add(node) + if (node.type is FilterNode) filtered.add(node) + } + + if (filtered.isNotEmpty()) return filtered + + return nextNodes + } + + override val pathfindingResistance: Double = 0.5 } data object WildcardSolidGlassNode : ItemNode { - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) override val pathfindingResistance: Double = 1.0 } - data object ItemMergeNode : ItemNode { - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true //TODO - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true //TODO - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) + data class ItemMergeNode(val direction: BlockFace) : ItemNode { + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset != direction + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset == direction + override fun getTransferableDirections(backwards: BlockFace): Set = setOf(direction) override val pathfindingResistance: Double = 1.0 } @@ -102,11 +117,10 @@ interface ItemNode : Node { val filter: WeakReference> = WeakReference(cache.holder.transportManager.filterManager.getFilter(position, FilterType.ItemType)!!) override val pathfindingResistance: Double = 1.0 - override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) - - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is InventoryNode + override fun getTransferableDirections(backwards: BlockFace): Set = setOf(face) - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode && other !is FilterNode + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode && other !is FilterNode override fun matches(itemStack: ItemStack): Boolean { return filter.get()?.matchesFilter(itemStack) == true @@ -114,14 +128,13 @@ interface ItemNode : Node { } data class HopperFilterNode(val position: BlockKey, var face: BlockFace, val cache: ItemTransportCache) : FilterNode, ComplexNode { - val globalPosition get() = cache.holder.transportManager.getGlobalCoordinate(toVec3i(position)) + private val globalPosition get() = cache.holder.transportManager.getGlobalCoordinate(toVec3i(position)) override val pathfindingResistance: Double = 1.0 override fun getTransferableDirections(backwards: BlockFace): Set = setOf(face) - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is InventoryNode - - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = other !is InventoryNode && other !is FilterNode + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = other !is ItemExtractorNode && other !is FilterNode override fun matches(itemStack: ItemStack): Boolean { val inventory = cache.getInventory(toBlockKey(globalPosition)) ?: return false @@ -135,7 +148,7 @@ interface ItemNode : Node { face = movement.displaceFace(face) } - fun getItemData(inventory: Inventory): Set { + private fun getItemData(inventory: Inventory): Set { val types = mutableSetOf() for (item: ItemStack? in inventory.contents) { diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt index 100ec3e5f8..d67423bed9 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/CacheType.kt @@ -1,6 +1,7 @@ package net.horizonsend.ion.server.features.transport.util import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks +import net.horizonsend.ion.server.features.custom.blocks.CustomBlocks.ITEM_FILTER import net.horizonsend.ion.server.features.starship.active.ActiveStarship import net.horizonsend.ion.server.features.transport.nodes.cache.FluidTransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.ItemTransportCache @@ -22,12 +23,21 @@ import net.horizonsend.ion.server.miscellaneous.utils.STAINED_GLASS_TYPES import net.horizonsend.ion.server.miscellaneous.utils.UNWAXED_CHISELED_COPPER_TYPES import net.horizonsend.ion.server.miscellaneous.utils.axis import org.bukkit.Material +import org.bukkit.Material.BARREL +import org.bukkit.Material.CHEST import org.bukkit.Material.CRAFTING_TABLE +import org.bukkit.Material.DAYLIGHT_DETECTOR +import org.bukkit.Material.DECORATED_POT +import org.bukkit.Material.DIAMOND_BLOCK +import org.bukkit.Material.DISPENSER +import org.bukkit.Material.DROPPER import org.bukkit.Material.END_ROD import org.bukkit.Material.FLETCHING_TABLE +import org.bukkit.Material.FURNACE import org.bukkit.Material.GLASS import org.bukkit.Material.GLASS_PANE import org.bukkit.Material.GRINDSTONE +import org.bukkit.Material.HOPPER import org.bukkit.Material.IRON_BLOCK import org.bukkit.Material.LAPIS_BLOCK import org.bukkit.Material.NOTE_BLOCK @@ -35,6 +45,7 @@ import org.bukkit.Material.OBSERVER import org.bukkit.Material.REDSTONE_BLOCK import org.bukkit.Material.SPONGE import org.bukkit.Material.TINTED_GLASS +import org.bukkit.Material.TRAPPED_CHEST import org.bukkit.Material.WAXED_CHISELED_COPPER import org.bukkit.Material.WAXED_EXPOSED_CHISELED_COPPER import org.bukkit.Material.WAXED_OXIDIZED_COPPER @@ -70,9 +81,9 @@ enum class CacheType(val namespacedKey: NamespacedKey) { }, SOLAR_PANELS(NamespacedKeys.POWER_TRANSPORT) { override val nodeCacheFactory: NodeCacheFactory = NodeCacheFactory.builder() - .addSimpleNode(Material.CRAFTING_TABLE, SolarPanelComponent.CraftingTable) - .addSimpleNode(Material.DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) - .addSimpleNode(Material.DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) + .addSimpleNode(CRAFTING_TABLE, SolarPanelComponent.CraftingTable) + .addSimpleNode(DIAMOND_BLOCK, SolarPanelComponent.DiamondBlock) + .addSimpleNode(DAYLIGHT_DETECTOR, SolarPanelComponent.DaylightDetector) .build() override fun get(chunk: IonChunk): SolarPanelCache { @@ -117,17 +128,17 @@ enum class CacheType(val namespacedKey: NamespacedKey) { .addSimpleNode(GLASS, SolidGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(GLASS_PANE, ItemNode.PaneGlassNode(ItemNode.PipeChannel.CLEAR)) .addSimpleNode(TINTED_GLASS, ItemNode.WildcardSolidGlassNode) - .addDataHandler(GRINDSTONE) { _, _, _ -> ItemNode.ItemMergeNode } - .addDataHandler(CustomBlocks.ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache, CustomBlocks.ITEM_FILTER.getFace(data)) } - .addDataHandler(Material.HOPPER) { data, key, holder -> ItemNode.HopperFilterNode(key, data.facing, holder.cache as ItemTransportCache) } + .addDataHandler(GRINDSTONE) { data, _, _ -> ItemNode.ItemMergeNode(data.facing) } + .addDataHandler(ITEM_FILTER) { data, key, holder -> ItemNode.AdvancedFilterNode(key, holder.cache as ItemTransportCache, ITEM_FILTER.getFace(data)) } + .addDataHandler(HOPPER) { data, key, holder -> ItemNode.HopperFilterNode(key, data.facing, holder.cache as ItemTransportCache) } .addSimpleNode( - Material.CHEST, - Material.TRAPPED_CHEST, - Material.BARREL, - Material.FURNACE, - Material.DISPENSER, - Material.DROPPER, - Material.DECORATED_POT + CHEST, + TRAPPED_CHEST, + BARREL, + FURNACE, + DISPENSER, + DROPPER, + DECORATED_POT ) { key, _, _ -> ItemNode.InventoryNode(key) } .build() @@ -138,9 +149,7 @@ enum class CacheType(val namespacedKey: NamespacedKey) { override fun get(ship: ActiveStarship): ItemTransportCache { return ship.transportManager.itemPipeManager.cache } - }, - - ; + }; abstract val nodeCacheFactory: NodeCacheFactory From b4989cf9caa1da716d7cb8933062449f82b68c98 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 6 Feb 2025 00:41:08 -0600 Subject: [PATCH 495/500] fix grindstone node --- .../features/transport/nodes/types/ItemNode.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 77facb67c5..7fb46d6355 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -102,10 +102,24 @@ interface ItemNode : Node { } data class ItemMergeNode(val direction: BlockFace) : ItemNode { - override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = offset != direction - override fun canTransferTo(other: Node, offset: BlockFace): Boolean = offset == direction + override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true + override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true override fun getTransferableDirections(backwards: BlockFace): Set = setOf(direction) + override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { + val forward = backwards.oppositeFace + + val filtered = mutableListOf() + for (node in nextNodes) { + if (node.offset == forward) filtered.add(node) + if (node.type is InventoryNode) filtered.add(node) + } + + if (filtered.isNotEmpty()) return filtered + + return nextNodes + } + override val pathfindingResistance: Double = 1.0 } From 63679e2f5841d87f0d7969919b7b42b35c774b3f Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 6 Feb 2025 00:46:29 -0600 Subject: [PATCH 496/500] invalidate path cache on node addition --- .../ion/server/features/transport/nodes/cache/TransportCache.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 8f7d33723a..55f30dd1ef 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -77,6 +77,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { val state = if (type == null) CacheState.Empty else CacheState.Present(type) nodeCache[location] = state + type?.let { pathCache.invalidatePaths(location, type) } return type } From a72fd17ecc61e68532b6476ad5de38ef10bd7f08 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 6 Feb 2025 01:38:48 -0600 Subject: [PATCH 497/500] probably fix silent stack overflow --- .../type/shipfactory/AdvancedShipFactoryMultiblock.kt | 3 ++- .../server/features/transport/nodes/cache/path/PathCache.kt | 2 +- .../ion/server/features/transport/util/NodePathfinding.kt | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt index 4016d93e96..c5569ad65e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt @@ -20,6 +20,7 @@ import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.util.CacheType +import net.horizonsend.ion.server.features.transport.util.getGlobalNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.BACKWARD import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.FORWARD @@ -175,7 +176,7 @@ object AdvancedShipFactoryMultiblock : AbstractShipFactoryMultiblock getGlobalNode(cacheType, world, key) }, null) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt index f466cb40f2..a57f9743b0 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt @@ -46,7 +46,7 @@ class PathCache(val cache: TransportCache) { return result } - fun invalidatePaths(pos: BlockKey, node: Node) { + fun invalidatePaths(pos: BlockKey, node: Node, cacheNewNodes: Boolean = false) { val toRemove = mutableSetOf>() // If the pos is an origin or destination, there is no need to perform a flood to find the connected rows / destinations diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt index 29684966e7..e02b66d874 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/util/NodePathfinding.kt @@ -20,6 +20,11 @@ fun getOrCacheNode(type: CacheType, world: World, pos: BlockKey): Node? { return type.get(chunk).getOrCache(pos) } +fun getGlobalNode(type: CacheType, world: World, pos: BlockKey): Node? { + val chunk = IonChunk[world, getX(pos).shr(4), getZ(pos).shr(4)] ?: return null + return type.get(chunk).getCached(pos) +} + const val MAX_PATHFINDS_OVER_BLOCK = 6 /** From 4e24d2f3e4e7cf37b1c2a4cb26b6651c6b546656 Mon Sep 17 00:00:00 2001 From: Gutin <57606752+Gutin1@users.noreply.github.com> Date: Thu, 6 Feb 2025 01:38:55 -0600 Subject: [PATCH 498/500] another merge node bug --- .../ion/server/features/transport/nodes/types/ItemNode.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt index 7fb46d6355..3f04a75532 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/types/ItemNode.kt @@ -104,7 +104,7 @@ interface ItemNode : Node { data class ItemMergeNode(val direction: BlockFace) : ItemNode { override fun canTransferFrom(other: Node, offset: BlockFace): Boolean = true override fun canTransferTo(other: Node, offset: BlockFace): Boolean = true - override fun getTransferableDirections(backwards: BlockFace): Set = setOf(direction) + override fun getTransferableDirections(backwards: BlockFace): Set = ADJACENT_BLOCK_FACES.minus(backwards) override fun filterPositionData(nextNodes: List, backwards: BlockFace): List { val forward = backwards.oppositeFace From 850c2089ae7cc4e98d25f6799bf64ed850192984 Mon Sep 17 00:00:00 2001 From: kwazedilla Date: Thu, 6 Feb 2025 01:43:42 -0800 Subject: [PATCH 499/500] WIP: more ship factory GUI buttons --- .../ion/server/features/gui/GuiItems.kt | 3 +++ .../AdvancedShipFactoryMultiblock.kt | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt index 1fd78f7d45..5cdeec0080 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/gui/GuiItems.kt @@ -228,6 +228,9 @@ enum class GuiItem(val modelKey: Key) : ItemProvider { COMPASS_NEEDLE(NamespacedKeys.packKey("ui/compass_needle")), BOOKMARK(NamespacedKeys.packKey("ui/bookmark")), SOUND(NamespacedKeys.packKey("ui/sound")), + OUTLINE(NamespacedKeys.packKey("ui/outline")), + ALIGN(NamespacedKeys.packKey("ui/align")), + MATERIALS(NamespacedKeys.packKey("ui/materials")), ; diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt index c5569ad65e..75a2643009 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt @@ -213,16 +213,23 @@ object AdvancedShipFactoryMultiblock : AbstractShipFactoryMultiblock Date: Thu, 6 Feb 2025 12:45:46 -0600 Subject: [PATCH 500/500] Actually fix the silent stackoverflow --- .../shipfactory/AdvancedShipFactoryMultiblock.kt | 3 +-- .../transport/nodes/cache/TransportCache.kt | 15 ++++++++------- .../transport/nodes/cache/path/PathCache.kt | 5 ++++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt index 75a2643009..1440706c82 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/multiblock/type/shipfactory/AdvancedShipFactoryMultiblock.kt @@ -20,7 +20,6 @@ import net.horizonsend.ion.server.features.transport.nodes.inputs.InputsData import net.horizonsend.ion.server.features.transport.nodes.types.ItemNode import net.horizonsend.ion.server.features.transport.nodes.types.Node.NodePositionData import net.horizonsend.ion.server.features.transport.util.CacheType -import net.horizonsend.ion.server.features.transport.util.getGlobalNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.BACKWARD import net.horizonsend.ion.server.miscellaneous.utils.coordinates.RelativeFace.FORWARD @@ -176,7 +175,7 @@ object AdvancedShipFactoryMultiblock : AbstractShipFactoryMultiblock getGlobalNode(cacheType, world, key) }, null) + getPreviousNodes(itemCacheHolder.nodeProvider, null) } } diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt index 55f30dd1ef..609ad78b2e 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/TransportCache.kt @@ -77,7 +77,7 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { val state = if (type == null) CacheState.Empty else CacheState.Present(type) nodeCache[location] = state - type?.let { pathCache.invalidatePaths(location, type) } + type?.let { pathCache.invalidatePaths(location, type, cacheNewNodes = false) } return type } @@ -202,14 +202,15 @@ abstract class TransportCache(open val holder: CacheHolder<*>) { val destinations = LongOpenHashSet() - visitQueue.addAll(originNode.getNextNodes( - world = holder.getWorld(), - position = originPos, - backwards = BlockFace.SELF, - holder.nodeProvider, - null + val nextNodes = nextNodeProvider.invoke(NodePositionData( + originNode, + holder.getWorld(), + originPos, + BlockFace.SELF )) + visitQueue.addAll(nextNodes) + var iterations = 0L val upperBound = 20_000 diff --git a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt index a57f9743b0..1a69b85be1 100644 --- a/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt +++ b/server/src/main/kotlin/net/horizonsend/ion/server/features/transport/nodes/cache/path/PathCache.kt @@ -4,6 +4,7 @@ import com.google.common.collect.TreeBasedTable import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache import net.horizonsend.ion.server.features.transport.nodes.cache.TransportCache.PathfindingReport import net.horizonsend.ion.server.features.transport.nodes.types.Node +import net.horizonsend.ion.server.features.transport.util.getGlobalNode import net.horizonsend.ion.server.miscellaneous.utils.coordinates.BlockKey import net.horizonsend.ion.server.miscellaneous.utils.set import java.util.Optional @@ -64,10 +65,12 @@ class PathCache(val cache: TransportCache) { } } + val nodeProvider = if (cacheNewNodes) cache.holder.nodeProvider else { cacheType, world, key -> getGlobalNode(cacheType, world, key) } + // Perform a flood fill to find all network destinations, then remove all destination columns cache.getNetworkDestinations(clazz = cache.extractorNodeClass, originPos = pos, originNode = node) { // Traverse network backwards - getPreviousNodes(cache.holder.nodeProvider, null) + getPreviousNodes(nodeProvider, null) }.forEach { extractorPos -> pathCache.rowMap()[extractorPos]?.keys?.forEach { columnKey -> toRemove.add(extractorPos to columnKey)