Skip to content

Commit

Permalink
Check for unit constructor validity
Browse files Browse the repository at this point in the history
  • Loading branch information
GlennFolker committed Mar 9, 2025
1 parent fd59708 commit 377335c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ _Sprite Packing:_ `./gradlew tools:pack`
### Server

Server builds are bundled with each released build (in Releases). If you'd rather compile on your own, replace 'desktop' with 'server', e.g. `gradlew server:dist`.

[LICENSE](LICENSE)
### Android

1. Install the Android SDK [here.](https://developer.android.com/studio#command-tools) Make sure you're downloading the "Command line tools only", as Android Studio is not required.
Expand Down
36 changes: 35 additions & 1 deletion core/src/mindustry/type/UnitType.java
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ public class UnitType extends UnlockableContent implements Senseable{
public UnitType(String name){
super(name);

// Try to immediately resolve the Unit constructor based on EntityMapping entry, if it is set.
// This is the default Vanilla behavior - it won't work properly for mods (see comment in `init()`)!
constructor = EntityMapping.map(this.name);
selectionSize = 30f;
}
Expand Down Expand Up @@ -695,10 +697,42 @@ protected void validateWeapons(){
public void init(){
super.init();

if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'");
if(constructor == null) throw new IllegalArgumentException(Strings.format("""
No constructor set up for unit '@': Assign `constructor = [your unit constructor]`. Vanilla defaults are:
"flying": UnitEntity::create
"mech": MechUnit::create
"legs": LegsUnit::create
"naval": UnitWaterMove::create
"payload": PayloadUnit::create
"missile": TimedKillUnit::create
"tank": TankUnit::create
"hover": ElevationMoveUnit::create
"tether": BuildingTetherPayloadUnit::create
"crawl": CrawlUnit::create
""", name));

// Often modders improperly only sets `constructor = ...` without mapping. Try to mitigate for that.
// In most cases, if the constructor is a Vanilla class, things should work just fine.
if(EntityMapping.map(name) == null) EntityMapping.nameMap.put(name, constructor);

Unit example = constructor.get();

// Sanity checks; this is an EXTREMELY COMMON pitfalls Java modders fall into.
int classId = example.classId();
if(
// Check if `classId()` even points to a valid constructor...
EntityMapping.map(classId) == null ||
// ...or if the class doesn't register itself and uses the ID of its base class.
classId != ((Entityc)EntityMapping.map(classId).get()).classId()
){
String type = example.getClass().getSimpleName();
throw new IllegalArgumentException(Strings.format("""
Invalid class ID for `@` detected (found: @). Fix it by:
- Register with `EntityMapping.register("some-unique-name", @::new)` to get an ID, and store it somewhere.
- Override `@#classId()` to return that ID.
""", type, classId, type, type));
}

allowLegStep = example instanceof Legsc;

//water preset
Expand Down

0 comments on commit 377335c

Please sign in to comment.