Partial 7.0 merge - API preview
This commit is contained in:
@@ -1,20 +1,26 @@
|
||||
package mindustry.mod;
|
||||
|
||||
import arc.struct.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
|
||||
/** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */
|
||||
@SuppressWarnings("deprecation")
|
||||
public class ClassMap{
|
||||
public static final ObjectMap<String, Class<?>> classes = new ObjectMap<>();
|
||||
|
||||
static{
|
||||
classes.put("BuilderAI", mindustry.ai.types.BuilderAI.class);
|
||||
classes.put("DefenderAI", mindustry.ai.types.DefenderAI.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("HugAI", mindustry.ai.types.HugAI.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("Ability", mindustry.entities.abilities.Ability.class);
|
||||
classes.put("EnergyFieldAbility", mindustry.entities.abilities.EnergyFieldAbility.class);
|
||||
classes.put("ForceFieldAbility", mindustry.entities.abilities.ForceFieldAbility.class);
|
||||
classes.put("MoveLightningAbility", mindustry.entities.abilities.MoveLightningAbility.class);
|
||||
classes.put("RepairFieldAbility", mindustry.entities.abilities.RepairFieldAbility.class);
|
||||
@@ -26,6 +32,7 @@ public class ClassMap{
|
||||
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("EmpBulletType", mindustry.entities.bullet.EmpBulletType.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);
|
||||
@@ -37,6 +44,7 @@ public class ClassMap{
|
||||
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("ExplosionEffect", mindustry.entities.effect.ExplosionEffect.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);
|
||||
@@ -45,8 +53,36 @@ public class ClassMap{
|
||||
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("AmmoType", mindustry.type.AmmoType.class);
|
||||
classes.put("AmmoTypes", mindustry.type.AmmoTypes.class);
|
||||
classes.put("ItemAmmoType", mindustry.type.AmmoTypes.ItemAmmoType.class);
|
||||
classes.put("PowerAmmoType", mindustry.type.AmmoTypes.PowerAmmoType.class);
|
||||
classes.put("Category", mindustry.type.Category.class);
|
||||
classes.put("ErrorContent", mindustry.type.ErrorContent.class);
|
||||
classes.put("Item", mindustry.type.Item.class);
|
||||
classes.put("ItemSeq", mindustry.type.ItemSeq.class);
|
||||
classes.put("ItemStack", mindustry.type.ItemStack.class);
|
||||
classes.put("Liquid", mindustry.type.Liquid.class);
|
||||
classes.put("LiquidStack", mindustry.type.LiquidStack.class);
|
||||
classes.put("Planet", mindustry.type.Planet.class);
|
||||
classes.put("Publishable", mindustry.type.Publishable.class);
|
||||
classes.put("Satellite", mindustry.type.Satellite.class);
|
||||
classes.put("Sector", mindustry.type.Sector.class);
|
||||
classes.put("SectorRect", mindustry.type.Sector.SectorRect.class);
|
||||
classes.put("SectorPreset", mindustry.type.SectorPreset.class);
|
||||
classes.put("StatusEffect", mindustry.type.StatusEffect.class);
|
||||
classes.put("TransitionHandler", mindustry.type.StatusEffect.TransitionHandler.class);
|
||||
classes.put("UnitType", mindustry.type.UnitType.class);
|
||||
classes.put("Weapon", mindustry.type.Weapon.class);
|
||||
classes.put("Weather", mindustry.type.Weather.class);
|
||||
classes.put("WeatherEntry", mindustry.type.Weather.WeatherEntry.class);
|
||||
classes.put("PointDefenseWeapon", mindustry.type.weapons.PointDefenseWeapon.class);
|
||||
classes.put("RepairBeamWeapon", mindustry.type.weapons.RepairBeamWeapon.class);
|
||||
classes.put("HealBeamMount", mindustry.type.weapons.RepairBeamWeapon.HealBeamMount.class);
|
||||
classes.put("MagneticStorm", mindustry.type.weather.MagneticStorm.class);
|
||||
classes.put("ParticleWeather", mindustry.type.weather.ParticleWeather.class);
|
||||
classes.put("RainWeather", mindustry.type.weather.RainWeather.class);
|
||||
classes.put("SolarFlare", mindustry.type.weather.SolarFlare.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);
|
||||
@@ -59,6 +95,8 @@ public class ClassMap{
|
||||
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("PayloadLaunchPad", mindustry.world.blocks.campaign.PayloadLaunchPad.class);
|
||||
classes.put("PayloadLaunchPadBuild", mindustry.world.blocks.campaign.PayloadLaunchPad.PayloadLaunchPadBuild.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);
|
||||
@@ -76,6 +114,7 @@ public class ClassMap{
|
||||
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("ItemEntry", mindustry.world.blocks.defense.turrets.ItemTurret.ItemEntry.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);
|
||||
@@ -99,6 +138,12 @@ public class ClassMap{
|
||||
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("Duct", mindustry.world.blocks.distribution.Duct.class);
|
||||
classes.put("DuctBuild", mindustry.world.blocks.distribution.Duct.DuctBuild.class);
|
||||
classes.put("DuctBridge", mindustry.world.blocks.distribution.DuctBridge.class);
|
||||
classes.put("DuctBridgeBuild", mindustry.world.blocks.distribution.DuctBridge.DuctBridgeBuild.class);
|
||||
classes.put("DuctRouter", mindustry.world.blocks.distribution.DuctRouter.class);
|
||||
classes.put("DuctBuild", mindustry.world.blocks.distribution.DuctRouter.DuctBuild.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);
|
||||
@@ -122,19 +167,22 @@ public class ClassMap{
|
||||
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("Prop", mindustry.world.blocks.environment.Prop.class);
|
||||
classes.put("Bush", Bush.class);
|
||||
classes.put("WavingProp", WavingProp.class);
|
||||
classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class);
|
||||
classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class);
|
||||
classes.put("StaticClusterWall", StaticClusterWall.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("WallOreBlock", mindustry.world.blocks.environment.WallOreBlock.class);
|
||||
classes.put("WobbleProp", mindustry.world.blocks.environment.WobbleProp.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);
|
||||
@@ -170,8 +218,26 @@ public class ClassMap{
|
||||
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("BallisticSilo", mindustry.world.blocks.payloads.BallisticSilo.class);
|
||||
classes.put("BallisticSiloBuild", mindustry.world.blocks.payloads.BallisticSilo.BallisticSiloBuild.class);
|
||||
classes.put("BlockForge", mindustry.world.blocks.payloads.BlockForge.class);
|
||||
classes.put("BlockForgeBuild", mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild.class);
|
||||
classes.put("BlockProducer", mindustry.world.blocks.payloads.BlockProducer.class);
|
||||
classes.put("BlockProducerBuild", mindustry.world.blocks.payloads.BlockProducer.BlockProducerBuild.class);
|
||||
classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class);
|
||||
classes.put("NuclearWarhead", mindustry.world.blocks.payloads.NuclearWarhead.class);
|
||||
classes.put("NuclearWarheadBuild", mindustry.world.blocks.payloads.NuclearWarhead.NuclearWarheadBuild.class);
|
||||
classes.put("Payload", mindustry.world.blocks.payloads.Payload.class);
|
||||
classes.put("PayloadBlock", mindustry.world.blocks.payloads.PayloadBlock.class);
|
||||
classes.put("PayloadBlockBuild", mindustry.world.blocks.payloads.PayloadBlock.PayloadBlockBuild.class);
|
||||
classes.put("PayloadMassDriver", mindustry.world.blocks.payloads.PayloadMassDriver.class);
|
||||
classes.put("PayloadDriverBuild", mindustry.world.blocks.payloads.PayloadMassDriver.PayloadDriverBuild.class);
|
||||
classes.put("PayloadDriverState", mindustry.world.blocks.payloads.PayloadMassDriver.PayloadDriverState.class);
|
||||
classes.put("PayloadMassDriverData", mindustry.world.blocks.payloads.PayloadMassDriver.PayloadMassDriverData.class);
|
||||
classes.put("PayloadSource", mindustry.world.blocks.payloads.PayloadSource.class);
|
||||
classes.put("PayloadSourceBuild", mindustry.world.blocks.payloads.PayloadSource.PayloadSourceBuild.class);
|
||||
classes.put("PayloadVoid", mindustry.world.blocks.payloads.PayloadVoid.class);
|
||||
classes.put("BlockLoaderBuild", mindustry.world.blocks.payloads.PayloadVoid.BlockLoaderBuild.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);
|
||||
@@ -201,8 +267,12 @@ public class ClassMap{
|
||||
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("AttributeCrafter", mindustry.world.blocks.production.AttributeCrafter.class);
|
||||
classes.put("AttributeCrafterBuild", mindustry.world.blocks.production.AttributeCrafter.AttributeCrafterBuild.class);
|
||||
classes.put("AttributeSmelter", mindustry.world.blocks.production.AttributeSmelter.class);
|
||||
classes.put("AttributeSmelterBuild", mindustry.world.blocks.production.AttributeSmelter.AttributeSmelterBuild.class);
|
||||
classes.put("BeamDrill", mindustry.world.blocks.production.BeamDrill.class);
|
||||
classes.put("BeamDrillBuild", mindustry.world.blocks.production.BeamDrill.BeamDrillBuild.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);
|
||||
@@ -223,6 +293,8 @@ public class ClassMap{
|
||||
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("SingleBlockProducer", mindustry.world.blocks.production.SingleBlockProducer.class);
|
||||
classes.put("SingleBlockProducerBuild", mindustry.world.blocks.production.SingleBlockProducer.SingleBlockProducerBuild.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);
|
||||
@@ -256,10 +328,14 @@ public class ClassMap{
|
||||
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("DrawArcSmelter", mindustry.world.draw.DrawArcSmelter.class);
|
||||
classes.put("DrawBlock", mindustry.world.draw.DrawBlock.class);
|
||||
classes.put("DrawCells", mindustry.world.draw.DrawCells.class);
|
||||
classes.put("DrawCultivator", mindustry.world.draw.DrawCultivator.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("DrawSmelter", mindustry.world.draw.DrawSmelter.class);
|
||||
classes.put("DrawWeave", mindustry.world.draw.DrawWeave.class);
|
||||
classes.put("Block", mindustry.world.Block.class);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import mindustry.entities.effect.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Objectives.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.mod.Mods.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.type.weather.*;
|
||||
@@ -59,6 +60,7 @@ public class ContentParser{
|
||||
return result;
|
||||
});
|
||||
put(Interp.class, (type, data) -> field(Interp.class, data));
|
||||
put(CacheLayer.class, (type, data) -> field(CacheLayer.class, data));
|
||||
put(Schematic.class, (type, data) -> {
|
||||
Object result = fieldOpt(Loadouts.class, data);
|
||||
if(result != null){
|
||||
@@ -132,7 +134,9 @@ public class ContentParser{
|
||||
return obj;
|
||||
});
|
||||
put(Weapon.class, (type, data) -> {
|
||||
Weapon weapon = new Weapon();
|
||||
var oc = resolve(data.getString("type", ""), Weapon.class);
|
||||
data.remove("type");
|
||||
var weapon = make(oc);
|
||||
readFields(weapon, data);
|
||||
weapon.name = currentMod.name + "-" + weapon.name;
|
||||
return weapon;
|
||||
@@ -325,8 +329,17 @@ public class ContentParser{
|
||||
return item;
|
||||
},
|
||||
ContentType.item, parser(ContentType.item, Item::new),
|
||||
ContentType.liquid, parser(ContentType.liquid, Liquid::new)
|
||||
//ContentType.sector, parser(ContentType.sector, SectorPreset::new)
|
||||
ContentType.liquid, parser(ContentType.liquid, Liquid::new),
|
||||
ContentType.status, parser(ContentType.status, StatusEffect::new),
|
||||
ContentType.sector, (TypeParser<SectorPreset>)(mod, name, value) -> {
|
||||
if(value.isString()){
|
||||
return locate(ContentType.sector, name);
|
||||
}
|
||||
|
||||
if(!value.has("sector") || !value.get("sector").isNumber()) throw new RuntimeException("SectorPresets must have a sector number.");
|
||||
|
||||
return new SectorPreset(name, locate(ContentType.planet, value.getString("planet", "serpulo")), value.getInt("sector"));
|
||||
}
|
||||
);
|
||||
|
||||
private Prov<Unit> unitType(JsonValue value){
|
||||
@@ -714,14 +727,10 @@ public class ContentParser{
|
||||
try{
|
||||
return (Class<T>)Class.forName(base);
|
||||
}catch(Exception ignored){
|
||||
//try to load from a mod's class loader
|
||||
for(LoadedMod mod : mods.mods){
|
||||
if(mod.loader != null){
|
||||
try{
|
||||
return (Class<T>)Class.forName(base, true, mod.loader);
|
||||
}catch(Exception ignore){}
|
||||
}
|
||||
}
|
||||
//try to use mod class loader
|
||||
try{
|
||||
return (Class<T>)Class.forName(base, true, mods.mainLoader());
|
||||
}catch(Exception ignore){}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
35
core/src/mindustry/mod/ModClassLoader.java
Normal file
35
core/src/mindustry/mod/ModClassLoader.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package mindustry.mod;
|
||||
|
||||
import arc.struct.*;
|
||||
|
||||
public class ModClassLoader extends ClassLoader{
|
||||
private Seq<ClassLoader> children = new Seq<>();
|
||||
private volatile boolean inChild = false;
|
||||
|
||||
public void addChild(ClassLoader child){
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
|
||||
//always try the superclass first
|
||||
try{
|
||||
return super.loadClass(name, resolve);
|
||||
}catch(ClassNotFoundException error){
|
||||
//a child may try to delegate class loading to its parent, which is *this class loader* - do not let that happen
|
||||
if(inChild) throw error;
|
||||
int size = children.size;
|
||||
//if it doesn't exist in the main class loader, try all the children
|
||||
for(int i = 0; i < size; i++){
|
||||
try{
|
||||
inChild = true;
|
||||
var out = children.get(i).loadClass(name);
|
||||
inChild = false;
|
||||
return out;
|
||||
}catch(ClassNotFoundException ignored){
|
||||
}
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.async.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.serialization.*;
|
||||
import arc.util.serialization.Jval.*;
|
||||
@@ -29,6 +30,7 @@ import java.util.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class Mods implements Loadable{
|
||||
private AsyncExecutor async = new AsyncExecutor();
|
||||
private Json json = new Json();
|
||||
private @Nullable Scripts scripts;
|
||||
private ContentParser parser = new ContentParser();
|
||||
@@ -37,15 +39,21 @@ public class Mods implements Loadable{
|
||||
|
||||
private int totalSprites;
|
||||
private MultiPacker packer;
|
||||
private ModClassLoader mainLoader = new ModClassLoader();
|
||||
|
||||
Seq<LoadedMod> mods = new Seq<>();
|
||||
private ObjectMap<Class<?>, ModMeta> metas = new ObjectMap<>();
|
||||
private boolean requiresReload, createdAtlas;
|
||||
private boolean requiresReload;
|
||||
|
||||
public Mods(){
|
||||
Events.on(ClientLoadEvent.class, e -> Core.app.post(this::checkWarnings));
|
||||
}
|
||||
|
||||
/** @return the main class loader for all mods */
|
||||
public ClassLoader mainLoader(){
|
||||
return mainLoader;
|
||||
}
|
||||
|
||||
/** Returns a file named 'config.json' in a special folder for the specified plugin.
|
||||
* Call this in init(). */
|
||||
public Fi getConfig(Mod mod){
|
||||
@@ -97,9 +105,7 @@ public class Mods implements Loadable{
|
||||
Core.settings.put("mod-" + loaded.name + "-enabled", true);
|
||||
sortMods();
|
||||
//try to load the mod's icon so it displays on import
|
||||
Core.app.post(() -> {
|
||||
loadIcon(loaded);
|
||||
});
|
||||
Core.app.post(() -> loadIcon(loaded));
|
||||
return loaded;
|
||||
}catch(IOException e){
|
||||
dest.delete();
|
||||
@@ -117,16 +123,37 @@ public class Mods implements Loadable{
|
||||
Time.mark();
|
||||
|
||||
packer = new MultiPacker();
|
||||
//all packing tasks to await
|
||||
var tasks = new Seq<AsyncResult<Runnable>>();
|
||||
|
||||
eachEnabled(mod -> {
|
||||
Seq<Fi> sprites = mod.root.child("sprites").findAll(f -> f.extension().equals("png"));
|
||||
Seq<Fi> overrides = mod.root.child("sprites-override").findAll(f -> f.extension().equals("png"));
|
||||
packSprites(sprites, mod, true);
|
||||
packSprites(overrides, mod, false);
|
||||
|
||||
packSprites(sprites, mod, true, tasks);
|
||||
packSprites(overrides, mod, false, tasks);
|
||||
|
||||
Log.debug("Packed @ images for mod '@'.", sprites.size + overrides.size, mod.meta.name);
|
||||
totalSprites += sprites.size + overrides.size;
|
||||
});
|
||||
|
||||
for(var result : tasks){
|
||||
try{
|
||||
var packRun = result.get();
|
||||
if(packRun != null){ //can be null for very strange reasons, ignore if that's the case
|
||||
try{
|
||||
//actually pack the image
|
||||
packRun.run();
|
||||
}catch(Exception e){ //the image can fail to fit in the spritesheet
|
||||
Log.err("Failed to fit image into the spritesheet, skipping.");
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
}catch(Exception e){ //this means loading the image failed, log it and move on
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
Log.debug("Time to pack textures: @", Time.elapsed());
|
||||
}
|
||||
|
||||
@@ -148,23 +175,29 @@ public class Mods implements Loadable{
|
||||
}
|
||||
}
|
||||
|
||||
private void packSprites(Seq<Fi> sprites, LoadedMod mod, boolean prefix){
|
||||
private void packSprites(Seq<Fi> sprites, LoadedMod mod, boolean prefix, Seq<AsyncResult<Runnable>> tasks){
|
||||
boolean linear = Core.settings.getBool("linear");
|
||||
|
||||
for(Fi file : sprites){
|
||||
try(InputStream stream = file.read()){
|
||||
byte[] bytes = Streams.copyBytes(stream, Math.max((int)file.length(), 512));
|
||||
Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
|
||||
packer.add(getPage(file), (prefix ? mod.name + "-" : "") + file.nameWithoutExtension(), new PixmapRegion(pixmap));
|
||||
pixmap.dispose();
|
||||
}catch(IOException e){
|
||||
Core.app.post(() -> {
|
||||
Log.err("Error packing images for mod: @", mod.meta.name);
|
||||
Log.err(e);
|
||||
if(!headless) ui.showException(e);
|
||||
});
|
||||
break;
|
||||
}
|
||||
//read and bleed pixmaps in parallel
|
||||
tasks.add(async.submit(() -> {
|
||||
try{
|
||||
Pixmap pix = new Pixmap(file.readBytes());
|
||||
//only bleeds when linear filtering is on at startup
|
||||
if(linear){
|
||||
Pixmaps.bleed(pix);
|
||||
}
|
||||
//this returns a *runnable* which actually packs the resulting pixmap; this has to be done synchronously outside the method
|
||||
return () -> {
|
||||
packer.add(getPage(file), (prefix ? mod.name + "-" : "") + file.nameWithoutExtension(), new PixmapRegion(pix));
|
||||
pix.dispose();
|
||||
};
|
||||
}catch(Exception e){
|
||||
//rethrow exception with details about the cause of failure
|
||||
throw new Exception("Failed to load image " + file + " for mod " + mod.name, e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
totalSprites += sprites.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,32 +209,77 @@ public class Mods implements Loadable{
|
||||
|
||||
//get textures packed
|
||||
if(totalSprites > 0){
|
||||
if(!createdAtlas) Core.atlas = new TextureAtlas(Core.files.internal("sprites/sprites.atlas"));
|
||||
createdAtlas = true;
|
||||
|
||||
for(AtlasRegion region : Core.atlas.getRegions()){
|
||||
//TODO PageType completely breaks down with multiple pages.
|
||||
PageType type = getPage(region);
|
||||
if(!packer.has(type, region.name)){
|
||||
packer.add(type, region.name, Core.atlas.getPixmap(region));
|
||||
packer.add(type, region.name, Core.atlas.getPixmap(region), region.splits, region.pads);
|
||||
}
|
||||
}
|
||||
|
||||
TextureFilter filter = Core.settings.getBool("linear") ? TextureFilter.linear : TextureFilter.nearest;
|
||||
Core.atlas.dispose();
|
||||
|
||||
//flush so generators can use these sprites
|
||||
packer.flush(filter, Core.atlas);
|
||||
//dead shadow-atlas for getting regions, but not pixmaps
|
||||
var shadow = Core.atlas;
|
||||
//dummy texture atlas that returns the 'shadow' regions; used for mod loading
|
||||
Core.atlas = new TextureAtlas(){
|
||||
|
||||
@Override
|
||||
public AtlasRegion find(String name){
|
||||
var base = packer.get(name);
|
||||
|
||||
if(base != null){
|
||||
var reg = new AtlasRegion(shadow.find(name).texture, base.x, base.y, base.width, base.height);
|
||||
reg.name = name;
|
||||
reg.pixmapRegion = base;
|
||||
return reg;
|
||||
}
|
||||
|
||||
return shadow.find(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(TextureRegion region){
|
||||
return region != shadow.find("error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureRegion find(String name, TextureRegion def){
|
||||
return !has(name) ? def : find(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean has(String s){
|
||||
return shadow.has(s) || packer.get(s) != null;
|
||||
}
|
||||
|
||||
//return the *actual* pixmap regions, not the disposed ones.
|
||||
@Override
|
||||
public PixmapRegion getPixmap(AtlasRegion region){
|
||||
PixmapRegion out = packer.get(region.name);
|
||||
//this should not happen in normal situations
|
||||
if(out == null) return packer.get("error");
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
TextureFilter filter = Core.settings.getBool("linear") ? TextureFilter.linear : TextureFilter.nearest;
|
||||
|
||||
//generate new icons
|
||||
for(Seq<Content> arr : content.getContentMap()){
|
||||
arr.each(c -> {
|
||||
if(c instanceof UnlockableContent u && c.minfo.mod != null){
|
||||
u.load();
|
||||
u.loadIcon();
|
||||
u.createIcons(packer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//dispose old atlas data
|
||||
Core.atlas = packer.flush(filter, new TextureAtlas());
|
||||
|
||||
Core.atlas.setErrorRegion("error");
|
||||
Log.debug("Total pages: @", Core.atlas.getTextures().size);
|
||||
}
|
||||
@@ -217,6 +295,7 @@ public class Mods implements Loadable{
|
||||
region.texture == Core.atlas.find("stone1").texture ? PageType.environment :
|
||||
region.texture == Core.atlas.find("clear-editor").texture ? PageType.editor :
|
||||
region.texture == Core.atlas.find("whiteui").texture ? PageType.ui :
|
||||
region.texture == Core.atlas.find("rubble-1-0").texture ? PageType.rubble :
|
||||
PageType.main;
|
||||
}
|
||||
|
||||
@@ -225,6 +304,7 @@ public class Mods implements Loadable{
|
||||
return
|
||||
parent.equals("environment") ? PageType.environment :
|
||||
parent.equals("editor") ? PageType.editor :
|
||||
parent.equals("rubble") ? PageType.editor :
|
||||
parent.equals("ui") || file.parent().parent().name().equals("ui") ? PageType.ui :
|
||||
PageType.main;
|
||||
}
|
||||
@@ -696,12 +776,12 @@ public class Mods implements Loadable{
|
||||
Version.isAtLeast(meta.minGameVersion) &&
|
||||
(meta.getMinMajor() >= 105 || headless)
|
||||
){
|
||||
|
||||
if(ios){
|
||||
throw new IllegalArgumentException("Java class mods are not supported on iOS.");
|
||||
}
|
||||
|
||||
loader = platform.loadJar(sourceFile, mainClass);
|
||||
loader = platform.loadJar(sourceFile, mainLoader);
|
||||
mainLoader.addChild(loader);
|
||||
Class<?> main = Class.forName(mainClass, true, loader);
|
||||
metas.put(main, meta);
|
||||
mainMod = (Mod)main.getDeclaredConstructor().newInstance();
|
||||
|
||||
@@ -25,12 +25,13 @@ public class Scripts implements Disposable{
|
||||
private static final Seq<String> 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.", "mod.classmap");
|
||||
private static final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "jdk.proxy1", "mindustry.gen.",
|
||||
"mindustry.logic.", "mindustry.async.", "saveio", "systemcursor", "filetreeinitevent");
|
||||
private static final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "jdk.proxy", "mindustry.gen.",
|
||||
"mindustry.logic.", "mindustry.async.", "saveio", "systemcursor", "filetreeinitevent", "asyncexecutor");
|
||||
|
||||
private final Context context;
|
||||
private final Scriptable scope;
|
||||
private boolean errored;
|
||||
|
||||
LoadedMod currentMod = null;
|
||||
|
||||
public static boolean allowClass(String type){
|
||||
@@ -41,10 +42,6 @@ public class Scripts implements Disposable{
|
||||
Time.mark();
|
||||
|
||||
context = Vars.platform.getScriptContext();
|
||||
context.setClassShutter(Scripts::allowClass);
|
||||
context.getWrapFactory().setJavaPrimitiveWrap(false);
|
||||
context.setLanguageVersion(Context.VERSION_ES6);
|
||||
|
||||
scope = new ImporterTopLevel(context);
|
||||
|
||||
new RequireBuilder()
|
||||
|
||||
Reference in New Issue
Block a user