diff --git a/assets/bundles/bundle.properties b/assets/bundles/bundle.properties index e69de29..1a98d91 100644 --- a/assets/bundles/bundle.properties +++ b/assets/bundles/bundle.properties @@ -0,0 +1,3 @@ +shar-stat.health = Health: {0} +shar-stat.shield = Shield: {0} +shar-stat.payloadCapacity = Payloads: {0} / {1} \ No newline at end of file diff --git a/assets/bundles/bundle_ko.properties b/assets/bundles/bundle_ko.properties new file mode 100644 index 0000000..af5571e --- /dev/null +++ b/assets/bundles/bundle_ko.properties @@ -0,0 +1,3 @@ +shar-stat.health = 체력: {0} +shar-stat.shield = 방어막: {0} +shar-stat.payloadCapacity = 화물: {0} / {1} \ No newline at end of file diff --git a/assets/mod.json b/assets/mod.json index edfbb39..a7fb0dd 100644 --- a/assets/mod.json +++ b/assets/mod.json @@ -1,11 +1,11 @@ { - "name": "modtemplate", - "displayName": "Template", - "author": "[#8738ff[]]Sonnicon[[]]", - "description": "Gradle jar Mindustry mod template", + "name": "unitinfo", + "displayName": "Unit Infomation", + "author": "Sharlotte", + "description": "The mod displays more information for unit, such as health, armor, shield, weapon/weapon reload etc", "version": "0", - "main": "sonnicon.modtemplate.ModTemplate", - "minGameVersion": "105", + "main": "UnitInfo.core.Main", + "minGameVersion": "126", "dependencies": [], "hidden": false, "java": true diff --git a/assets/sprites/icon.png b/assets/sprites/icon.png deleted file mode 100644 index bb43842..0000000 Binary files a/assets/sprites/icon.png and /dev/null differ diff --git a/assets/sprites/ui/bar-top.9.png b/assets/sprites/ui/bar-top.9.png new file mode 100644 index 0000000..c5049fe Binary files /dev/null and b/assets/sprites/ui/bar-top.9.png differ diff --git a/assets/sprites/ui/bar.9.png b/assets/sprites/ui/bar.9.png new file mode 100644 index 0000000..f2697f5 Binary files /dev/null and b/assets/sprites/ui/bar.9.png differ diff --git a/assets/sprites/ui/barS-top.png b/assets/sprites/ui/barS-top.png new file mode 100644 index 0000000..c09a4c8 Binary files /dev/null and b/assets/sprites/ui/barS-top.png differ diff --git a/assets/sprites/ui/barS.png b/assets/sprites/ui/barS.png new file mode 100644 index 0000000..2433420 Binary files /dev/null and b/assets/sprites/ui/barS.png differ diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..7f6358d --- /dev/null +++ b/build.bat @@ -0,0 +1,3 @@ +del /q C:\Users\lg\AppData\Roaming\Mindustry\mods\UnitInfo.jar; +move C:\Users\lg\Documents\GitHub\UnitInfo\build\libs\UnitInfo.jar C:\Users\lg\AppData\Roaming\Mindustry\mods; +java -jar C:\Users\lg\Desktop\Mindustry.jar \ No newline at end of file diff --git a/build.gradle b/build.gradle index e10c0ac..5216338 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,11 @@ plugins { group pGroup +version '1.0' + +sourceCompatibility = 8 + + sourceSets.main { java.srcDir("src/") resources.srcDir("assets/") @@ -14,12 +19,25 @@ repositories { maven { url "https://jitpack.io" } } -dependencies { - implementation "com.github.Anuken.Mindustry:core:$pMindustryVersion" -} - jar { archiveFileName.set pArtifactFilename + + from { + configurations.runtimeClasspath.collect { + it.isDirectory() ? it : zipTree(it) + } + } +} + + +dependencies { + implementation 'com.github.younggam:multi-lib:java-v1.1.0' + + compileOnly "com.github.Anuken.Arc:arc-core:$pMindustryVersion" + compileOnly "com.github.Anuken.Mindustry:core:$pMindustryVersion" + + compileOnly "com.github.Anuken.Mindustry:annotations:$pMindustryVersion" + annotationProcessor "com.github.Anuken.Mindustry:annotations:$pMindustryVersion" } task dexify(type: Jar) { diff --git a/gradle.properties b/gradle.properties index d08f8a3..ca7c139 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,8 @@ # Filename of output file (dexify prepends 'dexed-') (people will hate you if it isn't .jar) -pArtifactFilename = artifact.jar +pArtifactFilename = UnitInfo.jar # Group of project (should line up with dirs in src/) -pGroup = sonnicon +pGroup = sharlotte # Version of Mindustry to use (if not working, consult jitpack.io) -pMindustryVersion = v122 +pMindustryVersion = v126.2 # Minimum API level for d8 (if you don't know what this is, leave it unless d8 yells at you) pMinApi = 26 \ No newline at end of file diff --git a/src/UnitInfo/core/HudUi.java b/src/UnitInfo/core/HudUi.java new file mode 100644 index 0000000..8de1cb7 --- /dev/null +++ b/src/UnitInfo/core/HudUi.java @@ -0,0 +1,164 @@ +package UnitInfo.core; + +import UnitInfo.ui.SBar; +import arc.Core; +import arc.graphics.Color; +import arc.graphics.g2d.TextureRegion; +import arc.math.Mathf; +import arc.scene.ui.*; +import arc.scene.ui.layout.Stack; +import arc.scene.ui.layout.Table; +import arc.struct.Seq; +import arc.util.Log; +import arc.util.Scaling; +import mindustry.Vars; +import mindustry.entities.abilities.ForceFieldAbility; +import mindustry.entities.abilities.ShieldRegenFieldAbility; +import mindustry.entities.units.WeaponMount; +import mindustry.gen.*; +import mindustry.graphics.Pal; +import mindustry.type.UnitType; +import mindustry.type.Weapon; +import mindustry.ui.Bar; +import mindustry.ui.Cicon; + +import static arc.Core.scene; +import static mindustry.Vars.content; +import static mindustry.Vars.player; + +public class HudUi { + public Unit getUnit(){ + Seq units = Groups.unit.intersect(Core.input.mouseWorldX(), Core.input.mouseWorldY(), 4, 4); + if(units.size <= 0) return player.unit(); + Unit unit = units.peek(); + if(unit == null) return player.unit(); + else return unit; + } + + public void reset(Table table){ + table.remove(); + table.reset(); + addTable(); + } + + public void addTable(){ + Vars.ui.hudGroup.addChild(new Table(table -> { + Unit unit = getUnit(); + table.update(() -> { + if(getUnit() != unit) reset(table); + }); + table.left(); + table.table(scene.getStyle(Button.ButtonStyle.class).up, t -> { + t.table(Tex.underline2, tt -> { + tt.top(); + tt.add(new Stack(){{ + add(new Table(temp -> { + temp.left(); + temp.add(new Image(Icon.defense)).center(); + })); + add(new Table(temp -> { + temp.left(); + Label label = new Label(() -> (int)(getUnit().type == null ? 0 : getUnit().type.armor) + ""); + label.setColor(Pal.surge); + label.setSize(0.6f); + temp.add(label).center().padLeft(getUnit().type == null ? 0 : getUnit().type.armor < 10 ? 8f : 0f); + temp.pack(); + })); + }}).growX().left().padRight(3 * 8f); + tt.add(new Label(() ->{ + if(getUnit() != null && getUnit().type != null) return "[accent]" + getUnit().type.localizedName + "[]"; + return ""; + })).center(); + }); + t.defaults().size(25 * 8f); + t.row(); + t.table(tt -> { + tt.defaults().width(23 * 8f); + tt.defaults().height(4f * 8f); + tt.top(); + + tt.add(new SBar( + () -> Core.bundle.format("shar-stat.health", Mathf.round(getUnit().health,1)), + () -> Pal.health, + () -> Mathf.clamp(getUnit().health / getUnit().type.health) + )).growX().left(); + tt.row(); + tt.add(new SBar( + () -> Core.bundle.format("shar-stat.shield", Mathf.round(getUnit().shield,1)), + () -> Pal.surge, + () -> { + float max1 = ((ShieldRegenFieldAbility)content.units().copy().filter(ut -> ut.abilities.find(abil -> abil instanceof ShieldRegenFieldAbility) != null).sort(ut -> ((ShieldRegenFieldAbility)ut.abilities.find(abil -> abil instanceof ShieldRegenFieldAbility)).max).peek().abilities.find(abil -> abil instanceof ShieldRegenFieldAbility)).max; + float max2 = 0f; + if(getUnit().type.abilities.find(abil -> abil instanceof ForceFieldAbility) != null) max2 = ((ForceFieldAbility) getUnit().type.abilities.find(abil -> abil instanceof ForceFieldAbility)).max; + return Mathf.clamp(getUnit().shield / Math.max(max1, max2)); + } + )).growX().left(); + tt.row(); + if(getUnit() instanceof Payloadc) tt.add(new SBar( + () -> Core.bundle.format("shar-stat.payloadCapacity", Mathf.round(((Payloadc)getUnit()).payloadUsed()), Mathf.round(unit.type().payloadCapacity)), + () -> Pal.items, + () -> Mathf.clamp(((Payloadc)getUnit()).payloadUsed() / unit.type().payloadCapacity) + )).growX().left(); + + }); + }); + table.row(); + UnitType type = getUnit().type; + table.left(); + try{ + table.table(tx -> { + tx.defaults().minSize(24 * 8f); + tx.left(); + tx.table(scene.getStyle(Button.ButtonStyle.class).up, tt -> { + tt.defaults().minSize(8 * 8f); + tt.left(); + tt.top(); + + for(int r = 0; r < type.weapons.size; r++){ + final int i = r; + Weapon weapon = type.weapons.get(i); + WeaponMount mount = getUnit().mounts[i]; + TextureRegion region = !weapon.name.equals("") && weapon.outlineRegion.found() ? weapon.outlineRegion : type.icon(Cicon.full); + if(type.weapons.size > 1 && i % 3 == 0) tt.row(); + else if(i % 3 == 0) tt.row(); + tt.table(weapontable -> { + weapontable.left(); + weapontable.add(new Stack(){{ + add(new Table(o -> { + o.left(); + o.image(region).size(60).scaling(Scaling.bounded); + })); + + add(new Table(h -> { + h.add(new Stack(){{ + add(new Table(e -> { + e.defaults().growX().height(9).width(42f).padRight(2*8).padTop(8*2f); + Bar reloadBar = new Bar( + () -> "", + () -> Pal.accent.cpy().lerp(Color.orange, mount.reload / weapon.reload), + () -> mount.reload / weapon.reload); + e.add(reloadBar); + e.pack(); + })); + }}).padTop(2*8).padLeft(2*8); + h.pack(); + })); + }}).left(); + }).left(); + tt.center(); + } + }); + }); + }catch(Throwable err){ + Log.info(err); + } + + table.fillParent = true; + table.visibility = () -> + Vars.ui.hudfrag.shown && !Vars.ui.minimapfrag.shown() + && (!Vars.mobile || + !(getUnit().isBuilding() || Vars.control.input.block != null || !Vars.control.input.selectRequests.isEmpty() + && !(Vars.control.input.lastSchematic != null && !Vars.control.input.selectRequests.isEmpty()))); + })); + } +} diff --git a/src/UnitInfo/core/Main.java b/src/UnitInfo/core/Main.java new file mode 100644 index 0000000..9eb0266 --- /dev/null +++ b/src/UnitInfo/core/Main.java @@ -0,0 +1,28 @@ +package UnitInfo.core; + +import arc.Events; +import mindustry.game.EventType.*; +import mindustry.mod.Mod; + +public class Main extends Mod { + public Main(){ + Events.on(ClientLoadEvent.class, e -> { + new HudUi().addTable(); + }); + + Events.on(WorldLoadEvent.class, e -> { + new HudUi().addTable(); + }); + } + + @Override + public void init(){ + } + + @Override + public void loadContent(){ + + } + + +} diff --git a/src/UnitInfo/ui/SBar.java b/src/UnitInfo/ui/SBar.java new file mode 100644 index 0000000..8b4d1c7 --- /dev/null +++ b/src/UnitInfo/ui/SBar.java @@ -0,0 +1,138 @@ +package UnitInfo.ui; +import arc.*; +import arc.func.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.geom.*; +import arc.scene.*; +import arc.scene.style.*; +import arc.util.pooling.*; +import mindustry.gen.*; +import mindustry.ui.Fonts; + +public class SBar extends Element{ + private static Rect scissor = new Rect(); + + private Floatp fraction; + private String name = ""; + private float value, lastValue, blink; + private Color blinkColor = new Color(); + + + public SBar(String name, Color color, Floatp fraction){ + this.fraction = fraction; + this.name = Core.bundle.get(name, name); + this.blinkColor.set(color); + lastValue = value = fraction.get(); + setColor(color); + } + + public SBar(Prov name, Prov color, Floatp fraction){ + this.fraction = fraction; + try{ + lastValue = value = Mathf.clamp(fraction.get()); + }catch(Exception e){ //getting the fraction may involve referring to invalid data + lastValue = value = 0f; + } + update(() -> { + try{ + this.name = name.get(); + this.blinkColor.set(color.get()); + setColor(color.get()); + }catch(Exception e){ //getting the fraction may involve referring to invalid data + this.name = ""; + } + }); + } + + public SBar(){ + + } + + public void reset(float value){ + this.value = lastValue = blink = value; + } + + public void set(Prov name, Floatp fraction, Color color){ + this.fraction = fraction; + this.lastValue = fraction.get(); + this.blinkColor.set(color); + setColor(color); + update(() -> this.name = name.get()); + } + + public SBar blink(Color color){ + blinkColor.set(color); + return this; + } + + public Drawable drawable(String name){ + Drawable out = null; + + TextureAtlas.AtlasRegion region = Core.atlas.find(name); + + int[] splits = {10,10,9,9}; + NinePatch patch = new NinePatch(region, splits[0], splits[1], splits[2], splits[3]); + int[] pads = region.pads; + if(pads != null) patch.setPadding(pads[0], pads[1], pads[2], pads[3]); + out = new ScaledNinePatchDrawable(patch, 1f); + + return out; + } + + @Override + public void draw(){ + if(fraction == null) return; + + float computed; + try{ + computed = Mathf.clamp(fraction.get()); + }catch(Exception e){ //getting the fraction may involve referring to invalid data + computed = 0f; + } + + if(lastValue > computed){ + blink = 1f; + lastValue = computed; + } + + if(Float.isNaN(lastValue)) lastValue = 0; + if(Float.isInfinite(lastValue)) lastValue = 1f; + if(Float.isNaN(value)) value = 0; + if(Float.isInfinite(value)) value = 1f; + if(Float.isNaN(computed)) computed = 0; + if(Float.isInfinite(computed)) computed = 1f; + + blink = Mathf.lerpDelta(blink, 0f, 0.2f); + value = Mathf.lerpDelta(value, computed, 0.15f); + + NinePatchDrawable bar = (NinePatchDrawable) drawable("shar-barS"); + Draw.colorl(0.1f); + bar.draw(x, y, width, height); + Draw.color(color, blinkColor, blink); + + NinePatchDrawable top = (NinePatchDrawable) drawable("shar-barS-top"); + float topWidth = width * value; + + if(topWidth > Core.atlas.find("shar-bar-top").width){ + top.draw(x, y, topWidth, height); + }else{ + if(ScissorStack.push(scissor.set(x, y, topWidth, height))){ + top.draw(x, y, Core.atlas.find("shar-bar-top").width, height); + ScissorStack.pop(); + } + } + + Draw.color(); + + Font font = Fonts.outline; + GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); + lay.setText(font, name); + + font.setColor(Color.white); + font.draw(name, x + width / 2f - lay.width / 2f, y + height / 2f + lay.height / 2f + 1); + + Pools.free(lay); + } +} diff --git a/src/sonnicon/modtemplate/ModTemplate.java b/src/sonnicon/modtemplate/ModTemplate.java deleted file mode 100644 index 7011389..0000000 --- a/src/sonnicon/modtemplate/ModTemplate.java +++ /dev/null @@ -1,14 +0,0 @@ -package sonnicon.modtemplate; - -import mindustry.mod.Mod; - -public class ModTemplate extends Mod{ - - @Override - public void init(){ - } - - @Override - public void loadContent(){ - } -}