From a7188c48845dd423fc9b58bc6bcf6797f6d25b46 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 18 Feb 2021 13:11:20 -0500 Subject: [PATCH] Content parser class discovery improvements --- build.gradle | 2 +- core/src/mindustry/mod/ClassMap.java | 259 ++++++++++++++++++ core/src/mindustry/mod/ContentParser.java | 132 ++++----- core/src/mindustry/mod/Scripts.java | 13 +- core/src/mindustry/world/Block.java | 6 +- .../mindustry/tools/ScriptMainGenerator.java | 39 ++- 6 files changed, 379 insertions(+), 72 deletions(-) create mode 100644 core/src/mindustry/mod/ClassMap.java diff --git a/build.gradle b/build.gradle index 102c0babfd..cb151f6fb3 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ allprojects{ if(!project.hasProperty("versionType")) versionType = 'official' appName = 'Mindustry' steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256' - rhinoVersion = '2617981f706e50b8753155d8e15e326308be3b22' + rhinoVersion = '378626d8abc552bba57864358358045d2f2dbe9b' loadVersionProps = { return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p } diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java new file mode 100644 index 0000000000..5d650511fb --- /dev/null +++ b/core/src/mindustry/mod/ClassMap.java @@ -0,0 +1,259 @@ +package mindustry.mod; + +import arc.struct.*; +/** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */ +public class ClassMap{ + public static final ObjectMap> classes = new ObjectMap<>(); + + static{ + classes.put("BuilderAI", mindustry.ai.types.BuilderAI.class); + classes.put("FlyingAI", mindustry.ai.types.FlyingAI.class); + classes.put("FormationAI", mindustry.ai.types.FormationAI.class); + classes.put("GroundAI", mindustry.ai.types.GroundAI.class); + classes.put("LogicAI", mindustry.ai.types.LogicAI.class); + classes.put("MinerAI", mindustry.ai.types.MinerAI.class); + classes.put("RepairAI", mindustry.ai.types.RepairAI.class); + classes.put("SuicideAI", mindustry.ai.types.SuicideAI.class); + classes.put("ArtilleryBulletType", mindustry.entities.bullet.ArtilleryBulletType.class); + classes.put("BasicBulletType", mindustry.entities.bullet.BasicBulletType.class); + classes.put("BombBulletType", mindustry.entities.bullet.BombBulletType.class); + classes.put("BulletType", mindustry.entities.bullet.BulletType.class); + classes.put("ContinuousLaserBulletType", mindustry.entities.bullet.ContinuousLaserBulletType.class); + classes.put("FlakBulletType", mindustry.entities.bullet.FlakBulletType.class); + classes.put("LaserBoltBulletType", mindustry.entities.bullet.LaserBoltBulletType.class); + classes.put("LaserBulletType", mindustry.entities.bullet.LaserBulletType.class); + classes.put("LightningBulletType", mindustry.entities.bullet.LightningBulletType.class); + classes.put("LiquidBulletType", mindustry.entities.bullet.LiquidBulletType.class); + classes.put("MassDriverBolt", mindustry.entities.bullet.MassDriverBolt.class); + classes.put("MissileBulletType", mindustry.entities.bullet.MissileBulletType.class); + classes.put("PointBulletType", mindustry.entities.bullet.PointBulletType.class); + classes.put("RailBulletType", mindustry.entities.bullet.RailBulletType.class); + classes.put("SapBulletType", mindustry.entities.bullet.SapBulletType.class); + classes.put("ShrapnelBulletType", mindustry.entities.bullet.ShrapnelBulletType.class); + classes.put("MultiEffect", mindustry.entities.effect.MultiEffect.class); + classes.put("ParticleEffect", mindustry.entities.effect.ParticleEffect.class); + classes.put("WaveEffect", mindustry.entities.effect.WaveEffect.class); + classes.put("Objectives", mindustry.game.Objectives.class); + classes.put("Objective", mindustry.game.Objectives.Objective.class); + classes.put("Produce", mindustry.game.Objectives.Produce.class); + classes.put("Research", mindustry.game.Objectives.Research.class); + classes.put("SectorComplete", mindustry.game.Objectives.SectorComplete.class); + classes.put("ParticleWeather", mindustry.type.weather.ParticleWeather.class); + classes.put("RainWeather", mindustry.type.weather.RainWeather.class); + classes.put("Attributes", mindustry.world.blocks.Attributes.class); + classes.put("Autotiler", mindustry.world.blocks.Autotiler.class); + classes.put("AutotilerHolder", mindustry.world.blocks.Autotiler.AutotilerHolder.class); + classes.put("SliceMode", mindustry.world.blocks.Autotiler.SliceMode.class); + classes.put("ConstructBlock", mindustry.world.blocks.ConstructBlock.class); + classes.put("ConstructBuild", mindustry.world.blocks.ConstructBlock.ConstructBuild.class); + classes.put("ControlBlock", mindustry.world.blocks.ControlBlock.class); + classes.put("ItemSelection", mindustry.world.blocks.ItemSelection.class); + classes.put("Accelerator", mindustry.world.blocks.campaign.Accelerator.class); + classes.put("AcceleratorBuild", mindustry.world.blocks.campaign.Accelerator.AcceleratorBuild.class); + classes.put("LaunchPad", mindustry.world.blocks.campaign.LaunchPad.class); + classes.put("LaunchPadBuild", mindustry.world.blocks.campaign.LaunchPad.LaunchPadBuild.class); + classes.put("Door", mindustry.world.blocks.defense.Door.class); + classes.put("DoorBuild", mindustry.world.blocks.defense.Door.DoorBuild.class); + classes.put("ForceProjector", mindustry.world.blocks.defense.ForceProjector.class); + classes.put("ForceBuild", mindustry.world.blocks.defense.ForceProjector.ForceBuild.class); + classes.put("MendProjector", mindustry.world.blocks.defense.MendProjector.class); + classes.put("MendBuild", mindustry.world.blocks.defense.MendProjector.MendBuild.class); + classes.put("OverdriveProjector", mindustry.world.blocks.defense.OverdriveProjector.class); + classes.put("OverdriveBuild", mindustry.world.blocks.defense.OverdriveProjector.OverdriveBuild.class); + classes.put("ShockMine", mindustry.world.blocks.defense.ShockMine.class); + classes.put("ShockMineBuild", mindustry.world.blocks.defense.ShockMine.ShockMineBuild.class); + classes.put("Thruster", mindustry.world.blocks.defense.Thruster.class); + classes.put("ThrusterBuild", mindustry.world.blocks.defense.Thruster.ThrusterBuild.class); + classes.put("Wall", mindustry.world.blocks.defense.Wall.class); + classes.put("WallBuild", mindustry.world.blocks.defense.Wall.WallBuild.class); + classes.put("BaseTurret", mindustry.world.blocks.defense.turrets.BaseTurret.class); + classes.put("BaseTurretBuild", mindustry.world.blocks.defense.turrets.BaseTurret.BaseTurretBuild.class); + classes.put("ItemTurret", mindustry.world.blocks.defense.turrets.ItemTurret.class); + classes.put("ItemTurretBuild", mindustry.world.blocks.defense.turrets.ItemTurret.ItemTurretBuild.class); + classes.put("LaserTurret", mindustry.world.blocks.defense.turrets.LaserTurret.class); + classes.put("LaserTurretBuild", mindustry.world.blocks.defense.turrets.LaserTurret.LaserTurretBuild.class); + classes.put("LiquidTurret", mindustry.world.blocks.defense.turrets.LiquidTurret.class); + classes.put("LiquidTurretBuild", mindustry.world.blocks.defense.turrets.LiquidTurret.LiquidTurretBuild.class); + classes.put("PointDefenseTurret", mindustry.world.blocks.defense.turrets.PointDefenseTurret.class); + classes.put("PointDefenseBuild", mindustry.world.blocks.defense.turrets.PointDefenseTurret.PointDefenseBuild.class); + classes.put("PowerTurret", mindustry.world.blocks.defense.turrets.PowerTurret.class); + classes.put("PowerTurretBuild", mindustry.world.blocks.defense.turrets.PowerTurret.PowerTurretBuild.class); + classes.put("ReloadTurret", mindustry.world.blocks.defense.turrets.ReloadTurret.class); + classes.put("ReloadTurretBuild", mindustry.world.blocks.defense.turrets.ReloadTurret.ReloadTurretBuild.class); + classes.put("TractorBeamTurret", mindustry.world.blocks.defense.turrets.TractorBeamTurret.class); + classes.put("TractorBeamBuild", mindustry.world.blocks.defense.turrets.TractorBeamTurret.TractorBeamBuild.class); + classes.put("Turret", mindustry.world.blocks.defense.turrets.Turret.class); + classes.put("AmmoEntry", mindustry.world.blocks.defense.turrets.Turret.AmmoEntry.class); + classes.put("TurretBuild", mindustry.world.blocks.defense.turrets.Turret.TurretBuild.class); + classes.put("ArmoredConveyor", mindustry.world.blocks.distribution.ArmoredConveyor.class); + classes.put("ArmoredConveyorBuild", mindustry.world.blocks.distribution.ArmoredConveyor.ArmoredConveyorBuild.class); + classes.put("BufferedItemBridge", mindustry.world.blocks.distribution.BufferedItemBridge.class); + classes.put("BufferedItemBridgeBuild", mindustry.world.blocks.distribution.BufferedItemBridge.BufferedItemBridgeBuild.class); + classes.put("ChainedBuilding", mindustry.world.blocks.distribution.ChainedBuilding.class); + classes.put("Conveyor", mindustry.world.blocks.distribution.Conveyor.class); + classes.put("ConveyorBuild", mindustry.world.blocks.distribution.Conveyor.ConveyorBuild.class); + classes.put("ExtendingItemBridge", mindustry.world.blocks.distribution.ExtendingItemBridge.class); + classes.put("ExtendingItemBridgeBuild", mindustry.world.blocks.distribution.ExtendingItemBridge.ExtendingItemBridgeBuild.class); + classes.put("ItemBridge", mindustry.world.blocks.distribution.ItemBridge.class); + classes.put("ItemBridgeBuild", mindustry.world.blocks.distribution.ItemBridge.ItemBridgeBuild.class); + classes.put("Junction", mindustry.world.blocks.distribution.Junction.class); + classes.put("JunctionBuild", mindustry.world.blocks.distribution.Junction.JunctionBuild.class); + classes.put("MassDriver", mindustry.world.blocks.distribution.MassDriver.class); + classes.put("DriverBulletData", mindustry.world.blocks.distribution.MassDriver.DriverBulletData.class); + classes.put("DriverState", mindustry.world.blocks.distribution.MassDriver.DriverState.class); + classes.put("MassDriverBuild", mindustry.world.blocks.distribution.MassDriver.MassDriverBuild.class); + classes.put("OverflowGate", mindustry.world.blocks.distribution.OverflowGate.class); + classes.put("OverflowGateBuild", mindustry.world.blocks.distribution.OverflowGate.OverflowGateBuild.class); + classes.put("PayloadConveyor", mindustry.world.blocks.distribution.PayloadConveyor.class); + classes.put("PayloadConveyorBuild", mindustry.world.blocks.distribution.PayloadConveyor.PayloadConveyorBuild.class); + classes.put("PayloadRouter", mindustry.world.blocks.distribution.PayloadRouter.class); + classes.put("PayloadRouterBuild", mindustry.world.blocks.distribution.PayloadRouter.PayloadRouterBuild.class); + classes.put("Router", mindustry.world.blocks.distribution.Router.class); + classes.put("RouterBuild", mindustry.world.blocks.distribution.Router.RouterBuild.class); + classes.put("Sorter", mindustry.world.blocks.distribution.Sorter.class); + classes.put("SorterBuild", mindustry.world.blocks.distribution.Sorter.SorterBuild.class); + classes.put("StackConveyor", mindustry.world.blocks.distribution.StackConveyor.class); + classes.put("StackConveyorBuild", mindustry.world.blocks.distribution.StackConveyor.StackConveyorBuild.class); + classes.put("AirBlock", mindustry.world.blocks.environment.AirBlock.class); + classes.put("Boulder", mindustry.world.blocks.environment.Boulder.class); + classes.put("Cliff", mindustry.world.blocks.environment.Cliff.class); + classes.put("DoubleOverlayFloor", mindustry.world.blocks.environment.DoubleOverlayFloor.class); + classes.put("Floor", mindustry.world.blocks.environment.Floor.class); + classes.put("OreBlock", mindustry.world.blocks.environment.OreBlock.class); + classes.put("OverlayFloor", mindustry.world.blocks.environment.OverlayFloor.class); + classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class); + classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class); + classes.put("StaticTree", mindustry.world.blocks.environment.StaticTree.class); + classes.put("StaticWall", mindustry.world.blocks.environment.StaticWall.class); + classes.put("TreeBlock", mindustry.world.blocks.environment.TreeBlock.class); + classes.put("BlockForge", mindustry.world.blocks.experimental.BlockForge.class); + classes.put("BlockForgeBuild", mindustry.world.blocks.experimental.BlockForge.BlockForgeBuild.class); + classes.put("BlockLoader", mindustry.world.blocks.experimental.BlockLoader.class); + classes.put("BlockLoaderBuild", mindustry.world.blocks.experimental.BlockLoader.BlockLoaderBuild.class); + classes.put("BlockUnloader", mindustry.world.blocks.experimental.BlockUnloader.class); + classes.put("BlockUnloaderBuild", mindustry.world.blocks.experimental.BlockUnloader.BlockUnloaderBuild.class); + classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class); + classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class); + classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class); + classes.put("LegacyUnitFactory", mindustry.world.blocks.legacy.LegacyUnitFactory.class); + classes.put("LegacyUnitFactoryBuild", mindustry.world.blocks.legacy.LegacyUnitFactory.LegacyUnitFactoryBuild.class); + classes.put("ArmoredConduit", mindustry.world.blocks.liquid.ArmoredConduit.class); + classes.put("ArmoredConduitBuild", mindustry.world.blocks.liquid.ArmoredConduit.ArmoredConduitBuild.class); + classes.put("Conduit", mindustry.world.blocks.liquid.Conduit.class); + classes.put("ConduitBuild", mindustry.world.blocks.liquid.Conduit.ConduitBuild.class); + classes.put("LiquidBlock", mindustry.world.blocks.liquid.LiquidBlock.class); + classes.put("LiquidBuild", mindustry.world.blocks.liquid.LiquidBlock.LiquidBuild.class); + classes.put("LiquidBridge", mindustry.world.blocks.liquid.LiquidBridge.class); + classes.put("LiquidBridgeBuild", mindustry.world.blocks.liquid.LiquidBridge.LiquidBridgeBuild.class); + classes.put("LiquidExtendingBridge", mindustry.world.blocks.liquid.LiquidExtendingBridge.class); + classes.put("LiquidExtendingBridgeBuild", mindustry.world.blocks.liquid.LiquidExtendingBridge.LiquidExtendingBridgeBuild.class); + classes.put("LiquidJunction", mindustry.world.blocks.liquid.LiquidJunction.class); + classes.put("LiquidJunctionBuild", mindustry.world.blocks.liquid.LiquidJunction.LiquidJunctionBuild.class); + classes.put("LiquidRouter", mindustry.world.blocks.liquid.LiquidRouter.class); + classes.put("LiquidRouterBuild", mindustry.world.blocks.liquid.LiquidRouter.LiquidRouterBuild.class); + classes.put("LogicBlock", mindustry.world.blocks.logic.LogicBlock.class); + classes.put("LogicBuild", mindustry.world.blocks.logic.LogicBlock.LogicBuild.class); + classes.put("LogicLink", mindustry.world.blocks.logic.LogicBlock.LogicLink.class); + classes.put("LogicDisplay", mindustry.world.blocks.logic.LogicDisplay.class); + classes.put("GraphicsType", mindustry.world.blocks.logic.LogicDisplay.GraphicsType.class); + classes.put("LogicDisplayBuild", mindustry.world.blocks.logic.LogicDisplay.LogicDisplayBuild.class); + classes.put("MemoryBlock", mindustry.world.blocks.logic.MemoryBlock.class); + classes.put("MemoryBuild", mindustry.world.blocks.logic.MemoryBlock.MemoryBuild.class); + classes.put("MessageBlock", mindustry.world.blocks.logic.MessageBlock.class); + classes.put("MessageBuild", mindustry.world.blocks.logic.MessageBlock.MessageBuild.class); + classes.put("SwitchBlock", mindustry.world.blocks.logic.SwitchBlock.class); + classes.put("SwitchBuild", mindustry.world.blocks.logic.SwitchBlock.SwitchBuild.class); + classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class); + classes.put("Payload", mindustry.world.blocks.payloads.Payload.class); + classes.put("UnitPayload", mindustry.world.blocks.payloads.UnitPayload.class); + classes.put("Battery", mindustry.world.blocks.power.Battery.class); + classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class); + classes.put("BurnerGenerator", mindustry.world.blocks.power.BurnerGenerator.class); + classes.put("BurnerGeneratorBuild", mindustry.world.blocks.power.BurnerGenerator.BurnerGeneratorBuild.class); + classes.put("ConditionalConsumePower", mindustry.world.blocks.power.ConditionalConsumePower.class); + classes.put("DecayGenerator", mindustry.world.blocks.power.DecayGenerator.class); + classes.put("ImpactReactor", mindustry.world.blocks.power.ImpactReactor.class); + classes.put("ImpactReactorBuild", mindustry.world.blocks.power.ImpactReactor.ImpactReactorBuild.class); + classes.put("ItemLiquidGenerator", mindustry.world.blocks.power.ItemLiquidGenerator.class); + classes.put("ItemLiquidGeneratorBuild", mindustry.world.blocks.power.ItemLiquidGenerator.ItemLiquidGeneratorBuild.class); + classes.put("LightBlock", mindustry.world.blocks.power.LightBlock.class); + classes.put("LightBuild", mindustry.world.blocks.power.LightBlock.LightBuild.class); + classes.put("NuclearReactor", mindustry.world.blocks.power.NuclearReactor.class); + classes.put("NuclearReactorBuild", mindustry.world.blocks.power.NuclearReactor.NuclearReactorBuild.class); + classes.put("PowerBlock", mindustry.world.blocks.power.PowerBlock.class); + classes.put("PowerDiode", mindustry.world.blocks.power.PowerDiode.class); + classes.put("PowerDiodeBuild", mindustry.world.blocks.power.PowerDiode.PowerDiodeBuild.class); + classes.put("PowerDistributor", mindustry.world.blocks.power.PowerDistributor.class); + classes.put("PowerGenerator", mindustry.world.blocks.power.PowerGenerator.class); + classes.put("GeneratorBuild", mindustry.world.blocks.power.PowerGenerator.GeneratorBuild.class); + classes.put("PowerGraph", mindustry.world.blocks.power.PowerGraph.class); + classes.put("PowerNode", mindustry.world.blocks.power.PowerNode.class); + classes.put("PowerNodeBuild", mindustry.world.blocks.power.PowerNode.PowerNodeBuild.class); + classes.put("SingleTypeGenerator", mindustry.world.blocks.power.SingleTypeGenerator.class); + classes.put("SolarGenerator", mindustry.world.blocks.power.SolarGenerator.class); + classes.put("SolarGeneratorBuild", mindustry.world.blocks.power.SolarGenerator.SolarGeneratorBuild.class); + classes.put("ThermalGenerator", mindustry.world.blocks.power.ThermalGenerator.class); + classes.put("ThermalGeneratorBuild", mindustry.world.blocks.power.ThermalGenerator.ThermalGeneratorBuild.class); + classes.put("AttributeSmelter", mindustry.world.blocks.production.AttributeSmelter.class); + classes.put("AttributeSmelterBuild", mindustry.world.blocks.production.AttributeSmelter.AttributeSmelterBuild.class); + classes.put("Cultivator", mindustry.world.blocks.production.Cultivator.class); + classes.put("CultivatorBuild", mindustry.world.blocks.production.Cultivator.CultivatorBuild.class); + classes.put("Drill", mindustry.world.blocks.production.Drill.class); + classes.put("DrillBuild", mindustry.world.blocks.production.Drill.DrillBuild.class); + classes.put("Fracker", mindustry.world.blocks.production.Fracker.class); + classes.put("FrackerBuild", mindustry.world.blocks.production.Fracker.FrackerBuild.class); + classes.put("GenericCrafter", mindustry.world.blocks.production.GenericCrafter.class); + classes.put("GenericCrafterBuild", mindustry.world.blocks.production.GenericCrafter.GenericCrafterBuild.class); + classes.put("GenericSmelter", mindustry.world.blocks.production.GenericSmelter.class); + classes.put("SmelterBuild", mindustry.world.blocks.production.GenericSmelter.SmelterBuild.class); + classes.put("Incinerator", mindustry.world.blocks.production.Incinerator.class); + classes.put("IncineratorBuild", mindustry.world.blocks.production.Incinerator.IncineratorBuild.class); + classes.put("LiquidConverter", mindustry.world.blocks.production.LiquidConverter.class); + classes.put("LiquidConverterBuild", mindustry.world.blocks.production.LiquidConverter.LiquidConverterBuild.class); + classes.put("PayloadAcceptor", mindustry.world.blocks.production.PayloadAcceptor.class); + classes.put("PayloadAcceptorBuild", mindustry.world.blocks.production.PayloadAcceptor.PayloadAcceptorBuild.class); + classes.put("Pump", mindustry.world.blocks.production.Pump.class); + classes.put("PumpBuild", mindustry.world.blocks.production.Pump.PumpBuild.class); + classes.put("Separator", mindustry.world.blocks.production.Separator.class); + classes.put("SeparatorBuild", mindustry.world.blocks.production.Separator.SeparatorBuild.class); + classes.put("SolidPump", mindustry.world.blocks.production.SolidPump.class); + classes.put("SolidPumpBuild", mindustry.world.blocks.production.SolidPump.SolidPumpBuild.class); + classes.put("ItemSource", mindustry.world.blocks.sandbox.ItemSource.class); + classes.put("ItemSourceBuild", mindustry.world.blocks.sandbox.ItemSource.ItemSourceBuild.class); + classes.put("ItemVoid", mindustry.world.blocks.sandbox.ItemVoid.class); + classes.put("ItemVoidBuild", mindustry.world.blocks.sandbox.ItemVoid.ItemVoidBuild.class); + classes.put("LiquidSource", mindustry.world.blocks.sandbox.LiquidSource.class); + classes.put("LiquidSourceBuild", mindustry.world.blocks.sandbox.LiquidSource.LiquidSourceBuild.class); + classes.put("LiquidVoid", mindustry.world.blocks.sandbox.LiquidVoid.class); + classes.put("LiquidVoidBuild", mindustry.world.blocks.sandbox.LiquidVoid.LiquidVoidBuild.class); + classes.put("PowerSource", mindustry.world.blocks.sandbox.PowerSource.class); + classes.put("PowerSourceBuild", mindustry.world.blocks.sandbox.PowerSource.PowerSourceBuild.class); + classes.put("PowerVoid", mindustry.world.blocks.sandbox.PowerVoid.class); + classes.put("CoreBlock", mindustry.world.blocks.storage.CoreBlock.class); + classes.put("CoreBuild", mindustry.world.blocks.storage.CoreBlock.CoreBuild.class); + classes.put("StorageBlock", mindustry.world.blocks.storage.StorageBlock.class); + classes.put("StorageBuild", mindustry.world.blocks.storage.StorageBlock.StorageBuild.class); + classes.put("Unloader", mindustry.world.blocks.storage.Unloader.class); + classes.put("UnloaderBuild", mindustry.world.blocks.storage.Unloader.UnloaderBuild.class); + classes.put("CommandCenter", mindustry.world.blocks.units.CommandCenter.class); + classes.put("CommandBuild", mindustry.world.blocks.units.CommandCenter.CommandBuild.class); + classes.put("Reconstructor", mindustry.world.blocks.units.Reconstructor.class); + classes.put("ReconstructorBuild", mindustry.world.blocks.units.Reconstructor.ReconstructorBuild.class); + classes.put("RepairPoint", mindustry.world.blocks.units.RepairPoint.class); + classes.put("RepairPointBuild", mindustry.world.blocks.units.RepairPoint.RepairPointBuild.class); + classes.put("ResupplyPoint", mindustry.world.blocks.units.ResupplyPoint.class); + classes.put("ResupplyPointBuild", mindustry.world.blocks.units.ResupplyPoint.ResupplyPointBuild.class); + classes.put("UnitBlock", mindustry.world.blocks.units.UnitBlock.class); + classes.put("UnitBuild", mindustry.world.blocks.units.UnitBlock.UnitBuild.class); + classes.put("UnitFactory", mindustry.world.blocks.units.UnitFactory.class); + classes.put("UnitFactoryBuild", mindustry.world.blocks.units.UnitFactory.UnitFactoryBuild.class); + classes.put("UnitPlan", mindustry.world.blocks.units.UnitFactory.UnitPlan.class); + classes.put("DrawAnimation", mindustry.world.draw.DrawAnimation.class); + classes.put("DrawBlock", mindustry.world.draw.DrawBlock.class); + classes.put("DrawGlow", mindustry.world.draw.DrawGlow.class); + classes.put("DrawMixer", mindustry.world.draw.DrawMixer.class); + classes.put("DrawRotator", mindustry.world.draw.DrawRotator.class); + classes.put("DrawWeave", mindustry.world.draw.DrawWeave.class); + classes.put("Block", mindustry.world.Block.class); + } +} diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index c00ae23fe1..6467bd7813 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -15,10 +15,12 @@ import arc.util.serialization.*; import arc.util.serialization.Json.*; import arc.util.serialization.Jval.*; import mindustry.*; +import mindustry.ai.types.*; import mindustry.content.*; import mindustry.content.TechTree.*; import mindustry.ctype.*; import mindustry.entities.*; +import mindustry.entities.abilities.*; import mindustry.entities.bullet.*; import mindustry.entities.effect.*; import mindustry.game.*; @@ -26,6 +28,7 @@ import mindustry.game.Objectives.*; import mindustry.gen.*; import mindustry.mod.Mods.*; import mindustry.type.*; +import mindustry.type.weather.*; import mindustry.world.*; import mindustry.world.blocks.units.*; import mindustry.world.blocks.units.UnitFactory.*; @@ -42,14 +45,14 @@ public class ContentParser{ private static final boolean ignoreUnknownFields = true; ObjectMap, ContentType> contentTypes = new ObjectMap<>(); ObjectSet> implicitNullable = ObjectSet.with(TextureRegion.class, TextureRegion[].class, TextureRegion[][].class); - ObjectMap sounds = new ObjectMap<>(); + ObjectMap> sounds = new ObjectMap<>(); ObjectMap, FieldParser> classParsers = new ObjectMap<>(){{ put(Effect.class, (type, data) -> { if(data.isString()){ return field(Fx.class, data); } - Class bc = data.has("type") ? resolve(data.getString("type"), "mindustry.entities.effect") : ParticleEffect.class; + Class bc = resolve(data.getString("type", ""), ParticleEffect.class); data.remove("type"); Effect result = make(bc); readFields(result, data); @@ -83,12 +86,23 @@ public class ContentParser{ if(data.isString()){ return field(Bullets.class, data); } - Class bc = data.has("type") ? resolve(data.getString("type"), "mindustry.entities.bullet") : BasicBulletType.class; + var bc = resolve(data.getString("type", ""), BasicBulletType.class); data.remove("type"); BulletType result = make(bc); readFields(result, data); return result; }); + put(DrawBlock.class, (type, data) -> { + if(data.isString()){ + //try to instantiate + return make(resolve(data.asString())); + } + var bc = resolve(data.getString("type", ""), DrawBlock.class); + data.remove("type"); + var result = make(bc); + readFields(result, data); + return result; + }); put(Sound.class, (type, data) -> { if(fieldOpt(Sounds.class, data) != null) return fieldOpt(Sounds.class, data); if(Vars.headless) return new Sound(); @@ -104,12 +118,19 @@ public class ContentParser{ return sound; }); put(Objectives.Objective.class, (type, data) -> { - Class oc = data.has("type") ? resolve(data.getString("type"), "mindustry.game.Objectives") : SectorComplete.class; + var oc = resolve(data.getString("type", ""), SectorComplete.class); data.remove("type"); Objectives.Objective obj = make(oc); readFields(obj, data); return obj; }); + put(Ability.class, (type, data) -> { + Class oc = resolve(data.getString("type", "")); + data.remove("type"); + Ability obj = make(oc); + readFields(obj, data); + return obj; + }); put(Weapon.class, (type, data) -> { Weapon weapon = new Weapon(); readFields(weapon, data); @@ -118,12 +139,13 @@ public class ContentParser{ }); }}; /** Stores things that need to be parsed fully, e.g. reading fields of content. - * This is done to accomodate binding of content names first.*/ + * This is done to accommodate binding of content names first.*/ private Seq reads = new Seq<>(); private Seq postreads = new Seq<>(); private ObjectSet toBeParsed = new ObjectSet<>(); + LoadedMod currentMod; - private Content currentContent; + Content currentContent; private Json parser = new Json(){ @Override @@ -160,11 +182,6 @@ public class ContentParser{ } } - //try to load DrawBlock by instantiating it - if(type == DrawBlock.class && jsonData.isString()){ - return Reflect.make("mindustry.world.draw." + Strings.capitalize(jsonData.asString())); - } - if(Content.class.isAssignableFrom(type)){ ContentType ctype = contentTypes.getThrow(type, () -> new IllegalArgumentException("No content type for class: " + type.getSimpleName())); String prefix = currentMod != null ? currentMod.name + "-" : ""; @@ -194,30 +211,7 @@ public class ContentParser{ throw new IllegalArgumentException("When defining properties for an existing block, you must not re-declare its type. The original type will be used. Block: " + name); } }else{ - //TODO generate dynamically instead of doing.. this - Class type; - - try{ - type = resolve(getType(value), - "mindustry.world", - "mindustry.world.blocks", - "mindustry.world.blocks.defense", - "mindustry.world.blocks.defense.turrets", - "mindustry.world.blocks.distribution", - "mindustry.world.blocks.environment", - "mindustry.world.blocks.liquid", - "mindustry.world.blocks.logic", - "mindustry.world.blocks.power", - "mindustry.world.blocks.production", - "mindustry.world.blocks.sandbox", - "mindustry.world.blocks.storage", - "mindustry.world.blocks.units" - ); - }catch(IllegalArgumentException e){ - type = Block.class; - } - - block = make(type, mod + "-" + name); + block = make(resolve(getType(value), Block.class), mod + "-" + name); } currentContent = block; @@ -225,22 +219,19 @@ public class ContentParser{ read(() -> { if(value.has("consumes") && value.get("consumes").isObject()){ for(JsonValue child : value.get("consumes")){ - if(child.name.equals("item")){ - block.consumes.item(find(ContentType.item, child.asString())); - }else if(child.name.equals("items")){ - block.consumes.add((Consume)parser.readValue(ConsumeItems.class, child)); - }else if(child.name.equals("liquid")){ - block.consumes.add((Consume)parser.readValue(ConsumeLiquid.class, child)); - }else if(child.name.equals("power")){ - if(child.isNumber()){ - block.consumes.power(child.asFloat()); - }else{ - block.consumes.add((Consume)parser.readValue(ConsumePower.class, child)); + switch(child.name){ + case "item" -> block.consumes.item(find(ContentType.item, child.asString())); + case "items" -> block.consumes.add((Consume)parser.readValue(ConsumeItems.class, child)); + case "liquid" -> block.consumes.add((Consume)parser.readValue(ConsumeLiquid.class, child)); + case "power" -> { + if(child.isNumber()){ + block.consumes.power(child.asFloat()); + }else{ + block.consumes.add((Consume)parser.readValue(ConsumePower.class, child)); + } } - }else if(child.name.equals("powerBuffered")){ - block.consumes.powerBuffered(child.asFloat()); - }else{ - throw new IllegalArgumentException("Unknown consumption type: '" + child.name + "' for block '" + block.name + "'."); + case "powerBuffered" -> block.consumes.powerBuffered(child.asFloat()); + default -> throw new IllegalArgumentException("Unknown consumption type: '" + child.name + "' for block '" + block.name + "'."); } } value.remove("consumes"); @@ -308,7 +299,7 @@ public class ContentParser{ } if(value.has("controller")){ - unit.defaultController = make(resolve(value.getString("controller"), "mindustry.ai.types")); + unit.defaultController = supply(resolve(value.getString("controller"), FlyingAI.class)); } //read extra default waves @@ -334,8 +325,7 @@ public class ContentParser{ readBundle(ContentType.weather, name, value); }else{ readBundle(ContentType.weather, name, value); - Class type = resolve(getType(value), "mindustry.type.weather"); - item = make(type); + item = make(resolve(getType(value), ParticleWeather.class)); } currentContent = item; read(() -> readFields(item, value)); @@ -624,8 +614,8 @@ public class ContentParser{ JsonValue research = jsonMap.remove("research"); toBeParsed.remove(object); - Class type = object.getClass(); - ObjectMap fields = parser.getFields(type); + var type = object.getClass(); + var fields = parser.getFields(type); for(JsonValue child = jsonMap.child; child != null; child = child.next){ FieldMetadata metadata = fields.get(child.name().replace(" ", "_")); if(metadata == null){ @@ -654,7 +644,6 @@ public class ContentParser{ } } - if(object instanceof UnlockableContent unlock && research != null){ //add research tech node @@ -706,21 +695,34 @@ public class ContentParser{ } } - /** Tries to resolve a class from a list of potential class names. */ - Class resolve(String base, String... potentials){ + /** Tries to resolve a class from the class type map. */ + Class resolve(String base){ + return resolve(base, null); + } + + /** Tries to resolve a class from the class type map. */ + Class resolve(String base, Class def){ + //no base class specified + if(base.isEmpty() && def != null) return def; if(!base.isEmpty() && Character.isLowerCase(base.charAt(0))) base = Strings.capitalize(base); - for(String type : potentials){ + //return mapped class if found in the global map + var out = ClassMap.classes.get(base); + if(out != null) return (Class)out; + + //try to resolve it as a raw class name if it's allowed + if(base.indexOf('.') != -1 && Scripts.allowClass(base)){ try{ - return (Class)Class.forName(type + '.' + base); + return (Class)Class.forName(base); }catch(Exception ignored){ - try{ - return (Class)Class.forName(type + '$' + base); - }catch(Exception ignored2){ - } } } - throw new IllegalArgumentException("Types not found: " + base + "." + potentials[0]); + + if(def != null){ + Log.warn("[@] No type '" + base + "' found, defaulting to type '" + def.getSimpleName() + "'", currentContent == null ? currentMod.name : ""); + return def; + } + throw new IllegalArgumentException("Type not found: " + base); } private interface FieldParser{ diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java index ab3ffb89e5..1de3573f94 100644 --- a/core/src/mindustry/mod/Scripts.java +++ b/core/src/mindustry/mod/Scripts.java @@ -21,20 +21,25 @@ import java.net.*; import java.util.regex.*; public class Scripts implements Disposable{ - private final Seq blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", + private static final Seq blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", "runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system", - ".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org."); - private final Seq whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic.", "mindustry.async.", "saveio", "systemcursor", "filetreeinitevent"); + ".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org.", "mod.classmap"); + private static final Seq whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "mindustry.gen.", "mindustry.logic.", "mindustry.async.", "saveio", "systemcursor", "filetreeinitevent"); + private final Context context; private final Scriptable scope; private boolean errored; LoadedMod currentMod = null; + public static boolean allowClass(String type){ + return !blacklist.contains(type.toLowerCase()::contains) || whitelist.contains(type.toLowerCase()::contains); + } + public Scripts(){ Time.mark(); context = Vars.platform.getScriptContext(); - context.setClassShutter(type -> !blacklist.contains(type.toLowerCase()::contains) || whitelist.contains(type.toLowerCase()::contains)); + context.setClassShutter(Scripts::allowClass); context.getWrapFactory().setJavaPrimitiveWrap(false); context.setLanguageVersion(Context.VERSION_ES6); diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index da9702d902..17f86f69b7 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -335,7 +335,11 @@ public class Block extends UnlockableContent{ super.setStats(); stats.add(Stat.size, "@x@", size, size); - stats.add(Stat.health, health, StatUnit.none); + + if(synthetic()){ + stats.add(Stat.health, health, StatUnit.none); + } + if(canBeBuilt()){ stats.add(Stat.buildTime, buildCost / 60, StatUnit.seconds); stats.add(Stat.buildCost, new ItemListValue(false, requirements)); diff --git a/tools/src/mindustry/tools/ScriptMainGenerator.java b/tools/src/mindustry/tools/ScriptMainGenerator.java index 89e2839417..845d056f9a 100644 --- a/tools/src/mindustry/tools/ScriptMainGenerator.java +++ b/tools/src/mindustry/tools/ScriptMainGenerator.java @@ -14,6 +14,7 @@ import mindustry.game.*; import mindustry.gen.*; import mindustry.io.*; import mindustry.net.*; +import mindustry.world.*; import java.io.*; import java.lang.reflect.*; @@ -70,6 +71,40 @@ public class ScriptMainGenerator{ } new Fi("core/assets/scripts/global.js").writeString(result.toString()); + + //map simple name to type + Seq packages = Seq.with( + "mindustry.entities.effect", + "mindustry.entities.bullet", + "mindustry.ai.types", + "mindustry.type.weather", + "mindustry.game.Objectives", + "mindustry.world.blocks", + "mindustry.world.draw" + ); + + String classTemplate = "package mindustry.mod;\n" + + "\n" + + "import arc.struct.*;\n" + + "/** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */\n" + + "public class ClassMap{\n" + + " public static final ObjectMap> classes = new ObjectMap<>();\n" + + " \n" + + " static{\n$CLASSES$" + + " }\n" + + "}\n"; + + StringBuilder cdef = new StringBuilder(); + + Seq> mapped = classes.select(c -> Modifier.isPublic(c.getModifiers()) && packages.contains(c.getCanonicalName()::startsWith)) + .and(Block.class); //special case + + for(Class c : mapped){ + cdef.append(" classes.put(\"").append(c.getSimpleName()).append("\", ").append(c.getCanonicalName()).append(".class);\n"); + } + + new Fi("core/src/mindustry/mod/ClassMap.java").writeString(classTemplate.replace("$CLASSES$", cdef.toString())); + Log.info("Generated @ class mappings.", mapped.size); } public static Seq getClasses(String packageName) throws Exception{ @@ -103,7 +138,9 @@ public class ScriptMainGenerator{ String className = entry.getName().replace('/', '.'); className = className.substring(0, className.length() - ".class".length()); if(className.startsWith(packageName)){ - classes.add(Class.forName(className, false, Thread.currentThread().getContextClassLoader())); + Class res = Class.forName(className, false, Thread.currentThread().getContextClassLoader()); + classes.add(res); + //classes.addAll(res.getDeclaredClasses()); //???? } } }