Compare commits

..
Author SHA1 Message Date
Anuken a00e23e690 Fixed merge issue 2026-10-03 23:49:54 -04:00
Anuken ebbee02308 Fixed merge conflicts 2026-10-03 23:34:14 -04:00
Anuken 649f316f9f Merge branch 'v9' of https://github.com/Anuken/Mindustry into fixed-timestep
# Conflicts:
#	core/src/mindustry/core/Logic.java
#	core/src/mindustry/core/Renderer.java
#	core/src/mindustry/entities/EntityGroup.java
#	core/src/mindustry/world/blocks/distribution/Conveyor.java
#	core/src/mindustry/world/blocks/production/Drill.java
2026-10-03 23:32:16 -04:00
Anuken ed579e5ca4 Fixed compilation 2026-10-03 22:07:39 -04:00
Anuken f4ba7bd23a Merge remote-tracking branch 'origin/v9' into v9 2026-10-03 20:46:24 -04:00
Anuken 204e7280db Unused method cleanup 2026-10-03 20:46:18 -04:00
Anuken 222d71f4d2 State method moved 2026-10-03 18:28:11 -04:00
Anuken dd4a2b689f Merge remote-tracking branch 'origin/v9' into v9 2026-10-03 17:03:36 -04:00
Anuken bed1a35d07 Time refactor - moved to state 2026-10-03 17:02:52 -04:00
TwcashandAnuken d76f3d4aeb Metal renames (#12733)
* Directional unloader read fix

* Insert METAL between PANELS (lso give dark metal wall the wall name)

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-10-03 13:14:06 -04:00
EggleEgg a234c8ec9d updateClipRadius for buildTurret (#12738) 2026-10-03 13:13:42 -04:00
Anuken 7761d36cb8 Moved packer into arc-core 2026-10-03 12:40:49 -04:00
Anuken c1e3724d9f Fixed scroll inversion 2026-10-03 12:29:00 -04:00
Anuken 0cac59ec8c Merge branch 'v9' of https://github.com/Anuken/Mindustry into v9 2026-10-03 12:27:58 -04:00
Anuken 348113c23d Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-10-03 12:27:55 -04:00
Anuken a378c35fb6 Contribution guidelines & AI policy update 2026-10-03 11:07:11 -04:00
Anuken f688c81b9d Fixed integer scroll values 2026-10-02 23:58:37 -04:00
Anuken 34a23f2ae9 Misc fixes for tests 2026-10-02 20:00:39 -04:00
Anuken 39bc5c0f81 Switched to .kts build scripts 2026-10-02 16:25:10 -04:00
Anuken 0f2f962ac4 Threat assignment fix 2026-10-02 11:28:15 -04:00
Anuken a021e362ee Deleted leftover folders 2026-10-02 04:04:48 -04:00
Anuken 467cd51d5b Don't request GL 4.6 2026-10-02 04:02:25 -04:00
Anuken 7f6827d219 Fixed some test issues 2026-10-02 03:54:37 -04:00
Anuken 9dfd0ed49a Merge remote-tracking branch 'origin/v9' into v9 2026-10-02 03:47:02 -04:00
Anuken 6ef7c1509d Experimental graphical client tests for CI 2026-10-02 03:46:53 -04:00
Github Actions 0e09fbbc2c Automatic class mapping and map name update 2026-10-02 07:29:00 +00:00
Anuken 65ade81fb6 Arc merged into Mindustry; no more hash nonsense 2026-10-02 03:24:13 -04:00
Anuken 601ce4d35f Crash fix 2026-10-02 01:14:08 -04:00
Anuken b87f1d226b Fixed tests 2026-10-01 18:03:37 -04:00
Anuken 33a2d0a59e Updated build scripts for IJ compatibility 2026-10-01 15:59:14 -04:00
Anuken c1081205d6 nothing 2026-10-01 12:01:22 -04:00
Anuken fe5016c6fd Fixed compilation for server 2026-10-01 11:46:27 -04:00
Anuken ed017975cc arc 2026-09-30 22:55:32 -04:00
Anuken 2c1ee3a564 Cleanup 2026-09-30 22:33:37 -04:00
Anuken b90793c2fc Merge branch 'v9' of https://github.com/Anuken/Mindustry into new-icons 2026-09-30 22:29:04 -04:00
Anuken 606e88d683 Merge branch 'v9' of https://github.com/Anuken/Mindustry into v9 2026-09-30 22:28:47 -04:00
Anuken 294aeaad46 Fixed some missing reset() calls 2026-09-30 22:27:50 -04:00
Github Actions 8e519a0e24 Automatic class mapping and map name update 2026-10-01 00:29:24 +00:00
Anuken fc9b6067af Build fix 2026-09-30 20:26:57 -04:00
Anuken 24721e4aa0 Fixed process starting 2026-09-30 18:19:37 -04:00
Anuken b63b494e49 Merge branch 'v9' of https://github.com/Anuken/Mindustry into new-icons 2026-09-30 18:14:14 -04:00
Anuken 9863d3985d Codegen fix 2026-09-30 18:03:58 -04:00
Anuken 69ed90bb9d Directional unloader read fix 2026-09-30 18:02:13 -04:00
Anuken 7e825d4c30 Reverted the revert
This reverts commit e337452d46.
2026-09-30 17:59:42 -04:00
Anuken b1fff2ad15 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-09-30 17:59:22 -04:00
Anuken e337452d46 Reverted #12722 on master branch (will be back on v9)
This reverts commit 9f70386466.
2026-09-30 17:59:01 -04:00
Anuken 5809c4486b Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-09-30 17:58:08 -04:00
EggleEgg c8f4ec05f3 v9 bugfix: "absorbable" do your job (#12728) 2026-09-30 17:57:56 -04:00
Twcash 9f70386466 fix Copper ore color to match item color (#12722) 2026-09-30 17:56:38 -04:00
Cardillan e7de4e1a10 Fix empty statement fields shifting the remaining parameters (#12715)
* Fix empty statement fields shifting remaining parameters

* Fixed unit tests
2026-09-30 17:55:18 -04:00
Anuken 1ce95dc9c9 Massive logic name refactor 2026-09-30 17:54:02 -04:00
Anuken 30e3d1438c Split up instructions and statements 2026-09-30 17:48:05 -04:00
Anuken b09de7f881 Entity ID assignment moved to state 2026-09-30 17:37:28 -04:00
Anuken e39fd3d43a Timers removed from buildings 2026-09-30 17:15:10 -04:00
Anuken f7736b953c Merge branch 'v9' of https://github.com/Anuken/Mindustry into new-icons
# Conflicts:
#	gradle.properties
2026-09-30 16:55:04 -04:00
Anuken 1e3a9638ab Waves provider moved to a static method 2026-09-30 16:54:33 -04:00
Anuken c9f149d7c7 Async processes moved to state 2026-09-30 16:45:30 -04:00
Anuken 4e0a20d28d Cleanup 2026-09-30 16:34:00 -04:00
Anuken 47e4603391 Fog moved to state 2026-09-30 16:16:07 -04:00
Anuken 5d75db97f5 Pathfinding moved to state 2026-09-30 16:09:22 -04:00
Anuken 5a01cfefe4 Entity state refactor 2026-09-30 15:19:25 -04:00
Anuken 74d28ddc5d Cleanup 2026-09-30 14:44:02 -04:00
Anuken 1d1608da56 The tests pass, but at what cost? 2026-09-30 14:29:37 -04:00
Anuken 4bddd5f23b Cleanup 2026-09-30 13:59:14 -04:00
Anuken 15317122be State refactor (game actually works now) 2026-09-30 13:52:15 -04:00
Anuken 221b4a840b Massive state refactor, part 2 2026-09-30 12:47:07 -04:00
Anuken 2fb6d2503e Massive state refactor, part 1 2026-09-30 12:44:46 -04:00
Anuken 724bdc661a Fixed launch issue 2026-09-29 22:56:27 -04:00
Anuken 9caa1df777 Font fallback fixes 2026-09-29 21:54:46 -04:00
Anuken 3769737d33 Fixed some incremental font issues 2026-09-29 21:38:03 -04:00
Anuken 9780b09705 Moved runes into separate font 2026-09-29 21:16:37 -04:00
Anuken de480b9c18 Fixed some serialization issues & warnings 2026-09-29 16:31:03 -04:00
Anuken 0d3888343f Merge branch 'v9' into new-icons
# Conflicts:
#	gradle.properties
2026-09-29 15:16:40 -04:00
Anuken 74c31b272e Effect initialized noPatch 2026-09-29 15:16:27 -04:00
Anuken f93a746061 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-09-29 14:30:05 -04:00
WayZer 4cc15b84f6 Do not let content JSON set Effect#initialized (#12724) 2026-09-29 14:29:43 -04:00
Anuken f478112fd8 Updated icon to proper resolution, fixed icon on mac 2026-09-29 14:21:54 -04:00
Anuken a49ad98445 Merge remote-tracking branch 'origin/v9' into v9 2026-09-29 14:10:43 -04:00
Anuken 71799611bf Updated Android Gradle plugin (less painful this time I hope) 2026-09-29 14:10:35 -04:00
Github Actions ea38db6d06 Automatic class mapping and map name update 2026-09-29 17:39:06 +00:00
Anuken 61156bf527 Patcher system refactor 2026-09-29 13:36:58 -04:00
Anuken 4b27c6ece4 Fixed MacOS icon and export 2026-09-29 13:10:09 -04:00
Anuken 8d4b4b4851 Initial setup for new icons 2026-09-29 10:08:54 -04:00
Anuken 88dc7efbe2 Minor icon tweak 2026-09-28 18:51:21 -04:00
Anuken b25ffe9516 New icon 2026-09-28 17:44:23 -04:00
Anuken fedb8b8366 Minor sprite gen cleanup 2026-09-28 17:04:10 -04:00
Anuken fb29be30fa Fixed status effect icons 2026-09-28 13:47:39 -04:00
Anuken 4985dee0ad Autotiling moved to shared packing code 2026-09-28 13:26:43 -04:00
Anuken f3bfa418a5 Fixed rare physics crash 2026-09-27 18:45:23 -04:00
Anuken 0a7afa3e7c Pixmap outline API change 2026-09-27 12:17:12 -04:00
Anuken 813d47895d Merge remote-tracking branch 'origin/v9' into v9 2026-09-25 17:45:25 -04:00
Anuken 43936c0150 Fixed tests 2026-09-25 17:45:19 -04:00
Github Actions 4b525a8a84 Automatic class mapping and map name update 2026-09-25 21:19:15 +00:00
Anuken 79eaa03abd Custom difficulty support for mods 2026-09-25 17:17:01 -04:00
Anuken 2d9010dc2d Merge remote-tracking branch 'origin/v9' into v9 2026-09-25 17:11:20 -04:00
Anuken 1641cde4b7 Conditions refactored 2026-09-25 17:11:12 -04:00
Github Actions ac31e065ab Automatic class mapping and map name update 2026-09-25 21:10:01 +00:00
Anuken f29d00ee0a Merge remote-tracking branch 'origin/v9' into v9 2026-09-25 17:08:11 -04:00
Anuken c35c1b37b3 Massive package & objective refactor 2026-09-25 17:08:00 -04:00
Github Actions 7fb87c6d08 Automatic class mapping and map name update 2026-09-25 21:00:39 +00:00
Anuken 174791cdd4 Fixed player events not having proper suffix 2026-09-25 16:58:41 -04:00
Anuken 305cf07c75 Fixed SMAA crash 2026-09-25 16:54:22 -04:00
Anuken 22c63a3ffa Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/ClientLauncher.java
#	core/src/mindustry/mod/DataManager.java
2026-09-25 16:48:21 -04:00
Anuken 663b0b8737 Backported patch loading in mods from v9 for future compatibility 2026-09-25 16:47:42 -04:00
Anuken 3bd96cb383 Fixed mod patch loading 2026-09-25 16:44:38 -04:00
Anuken 765f4842eb Merge remote-tracking branch 'origin/v9' into v9 2026-09-25 13:01:37 -04:00
Anuken 5c19b87425 Fixed some content image loading issues 2026-09-25 13:01:26 -04:00
Anuken 0645f6f82d Removed defunct allure test 2026-09-25 11:42:11 -04:00
Anuken 871f3256cb JSON mods now use patches, not content overriding 2026-09-25 11:40:14 -04:00
Anuken e30eaa3001 WIP glow corner 2026-09-25 10:57:37 -04:00
Github Actions b2b541c880 Automatic class mapping and map name update 2026-09-24 16:56:48 +00:00
Anuken 624df89739 Refactored sector threat to enum, fixed some icon bugs 2026-09-24 12:54:27 -04:00
Anuken 34772a337e Fixed quad marker 2026-09-24 04:12:07 -04:00
Anuken 29bd7c877a NinePatch tint support 2026-09-24 02:04:19 -04:00
Anuken 28fd4b2663 Fixed corner pixmap upload 2026-09-24 00:22:42 -04:00
Anuken a71c473d01 Fixed some bugs with the new texture packing 2026-09-23 23:53:01 -04:00
Anuken d0e9c2767a Cleanup & tools sprite generation performance improvement 2026-09-23 19:15:53 -04:00
Anuken 0a316ff99e Unification of mod and vanilla sprite generation logic 2026-09-23 15:38:09 -04:00
Anuken b1f269a5fc Fixed some issues with naval unit crush damage 2026-09-23 09:33:07 -04:00
Anuken a4ce362e4b Cleanup 2026-09-22 20:58:26 -04:00
Anuken 992db3ed7b SMAA on by default for desktop discrete GPUs 2026-09-22 17:43:00 -04:00
Anuken cbd19fb4fa Fixed floor rendering/linear filtering issues on phones 2026-09-22 16:54:22 -04:00
Anuken 7fe820f7fb Alternate optimization for shields 2026-09-22 16:37:09 -04:00
Anuken 378e20478d Shield bounds check for rendering 2026-09-22 16:08:42 -04:00
Anuken fddac9c821 Better shield shader 2026-09-22 15:51:28 -04:00
Anuken 0faddee3c8 Make force projectors vulnerable when first placed 2026-09-22 12:44:08 -04:00
Anuken 733db5035b Fixed sap bullets being able to pierce shields + placeholder balance adjustment for Eclipse lasers 2026-09-21 19:53:52 -04:00
Anuken 0011a1503a Shield absorption support for flame/point laser bullets 2026-09-21 19:32:52 -04:00
Anuken 8396d5c9fa Made setStats accept an object instead of using an instance field 2026-09-21 15:48:14 -04:00
Anuken 318ca1cc8e Cleanup 2026-09-21 15:42:20 -04:00
Anuken 13597bc402 Begin refactoring mod sprite packing 2026-09-21 15:15:33 -04:00
Anuken 6a9b816f84 Visual artifact fixes for Erekir core units + orbit rendering tweaks 2026-09-21 13:24:07 -04:00
Anuken 9e06c7f88f Merge remote-tracking branch 'origin/v9' into v9 2026-09-21 11:52:23 -04:00
Anuken da62ba6e2a Fixed visual artifacts between cell and highlights on Serpulo core units 2026-09-21 11:52:14 -04:00
Github Actions 0dffe0ee2b Automatic bundle update 2026-09-21 05:58:47 +00:00
Anuken db57f0cf91 Merge remote-tracking branch 'origin/v9' into v9 2026-09-21 01:57:55 -04:00
Anuken d7d0506e3f Antialiasing (SMAA) implementation 2026-09-21 01:57:43 -04:00
Github Actions 162083a0d5 Automatic class mapping and map name update 2026-09-21 04:53:38 +00:00
Anuken 65da207421 Merge remote-tracking branch 'origin/v9' into v9 2026-09-21 00:51:28 -04:00
Anuken 4969d0423f Explosion absorption fixes with shields 2026-09-21 00:50:39 -04:00
Anuken 59d11e56a5 Made unit shields absorb lasers/bullets too 2026-09-21 00:35:56 -04:00
Anuken c92cd927d1 WIP: shields absorb rail/laser bullets 2026-09-21 00:04:42 -04:00
Github Actions 979ba53b56 Automatic class mapping and map name update 2026-09-21 03:38:25 +00:00
Anuken 081409e687 Refactored shield provider interface 2026-09-20 23:36:14 -04:00
Anuken 9aca7ec86d Fixed door solid check 2026-09-20 22:57:29 -04:00
Anuken 3a54813513 Fixed some schema generation bugs 2026-09-20 18:40:01 -04:00
Anuken 8b6fe795d2 Better unit drown effect 2026-09-20 18:24:04 -04:00
Anuken 9426d4c670 Naval unit collisions + ramming with conveyors 2026-09-20 18:06:37 -04:00
Anuken 4dcadcf3cf Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-09-20 17:28:10 -04:00
Anuken 3e43d88374 WIP re-generation of regions on server 2026-09-20 17:27:51 -04:00
Anuken 580f8f5217 Fixed #12697 2026-09-20 13:55:06 -04:00
Github Actions 067c720a88 Automatic bundle update 2026-09-20 13:22:06 +00:00
Kevin Vilyan 2541682bee Update Bundle ID (#12693) 2026-09-20 09:21:29 -04:00
Vector 78921a064e Update bundle_es.properties (#12672)
* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties

* sensor descriptions

* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties
2026-09-20 09:21:19 -04:00
Sunky.MP3G 92d53b01fc More RU translations (#12639)
* New RU translations and proper processor ones

* Finished

* Typo
2026-09-20 09:21:11 -04:00
Anuken 8f1a4c5541 Merge remote-tracking branch 'origin/master' 2026-09-20 09:21:00 -04:00
Anuken e2ccb6ea96 Fixed #12691 2026-09-20 09:20:54 -04:00
EggleEgg 2f3a3979a4 Bugfix lightning chain distance (again) (#12695) 2026-09-20 09:19:40 -04:00
Anuken 9f065cea59 Do not add liquid bars to blocks with 0 liquid capacity 2026-09-19 23:24:54 -04:00
Anuken 0650d5ae41 Animated surface setting cleanup 2026-09-19 12:18:09 -04:00
Anuken d2c5e09413 Fixed popups not respecting hidden UI state 2026-09-19 11:43:05 -04:00
Anuken 1cc5d54fde Fixed #12690 2026-09-19 10:53:14 -04:00
Anuken 4ef2a6d81e CADisableMinimumFrameDurationOnPhone on iOS 2026-09-18 18:04:25 -04:00
Anuken be14e4173e Null check for displayFlow 2026-09-18 13:58:24 -04:00
Anuken c58aac5f67 Version-specific release fetching for mods 2026-09-18 12:47:14 -04:00
Anuken cada4b2543 Logic parsing tests 2026-09-18 11:11:56 -04:00
summoner ccc5bebc3b Translation: Update bundle_hu.properties (#12679)
Follow the changes of the english bundle
Minor fixes
2026-09-18 10:47:37 -04:00
Anuken 8b80186320 Merge remote-tracking branch 'origin/master' 2026-09-18 10:47:15 -04:00
Anuken 1e8317fbac Fixed #12683 2026-09-18 10:47:09 -04:00
Cardillan 6500b5b6de Improve hex and binary literal parses (#12678)
* Improve hex and binary literal parses

* Moved the specialized unsigned long parsing routine from Strings directly to LAssembler
2026-09-18 10:46:33 -04:00
Anuken eff677e112 Merge remote-tracking branch 'origin/master' 2026-09-18 10:17:56 -04:00
Anuken 543dae701c Updated PR template 2026-09-18 10:17:43 -04:00
Anuken ec2bc54339 Fixed #12677 2026-09-18 10:17:43 -04:00
Anuken 2b2c3f8d30 Updated PR template 2026-09-18 10:17:13 -04:00
Anuken 772bf60a3c Fixed #12677 2026-09-17 18:31:36 -04:00
EggleEgg ca2c51896d Bugfix: scaled crafters unable to dump fast enough (#12669) 2026-09-17 11:10:16 -04:00
Anuken c640ae21ad Merge remote-tracking branch 'origin/master' 2026-09-17 10:54:56 -04:00
Anuken b8f392a116 Fixed #12674 2026-09-17 10:54:49 -04:00
EggleEgg bfa31bf184 Bugfix: attributecrafter yield string format (#12675)
* Bugfix: attributecrafter yield string format

* imports
2026-09-17 10:51:59 -04:00
Anuken 088486c1ad Fixed #12673 2026-09-17 10:51:38 -04:00
Anuken acf891e419 Mod matching release WIP 2026-09-16 15:40:41 -04:00
Anuken ca90af5f56 Updated steamworks 2026-09-16 12:42:44 -04:00
Anuken fc1761d6fe Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/mod/DataImagePacker.java
2026-09-16 10:18:34 -04:00
Anuken 45b82b9fa2 Merge remote-tracking branch 'origin/master' 2026-09-16 10:18:06 -04:00
Anuken 22cf431170 Fixed incorrect texture removal 2026-09-16 10:17:59 -04:00
Acts1631 b513d92456 Deduplicate requested assets during handshake (#12667)
* Deduplicate requested assets during handshake

* Use Bits for asset request deduplication
2026-09-15 20:34:09 -04:00
Anuken b3be63437e Better player name wrapping in player list 2026-09-15 12:13:12 -04:00
Anuken c801b625ac Merge remote-tracking branch 'origin/master' 2026-09-15 00:39:53 -04:00
Anuken 0bbc4c6777 Fixed #12660 2026-09-15 00:39:46 -04:00
sora54 4eed142ccc Fix cluster array dimension to use costTypes size (#12658) 2026-09-15 00:19:59 -04:00
EggleEgg 42ec5c9685 Bugfix: cap lightning distance (#12659) 2026-09-15 00:03:44 -04:00
summoner ca9876544e Translation: Update bundle_hu.properties (#12661)
* Translation: Update bundle_hu.properties

Fixing sentences
Fixing wording

* Translation: Update bundle_hu.properties

More fixes
2026-09-15 00:03:23 -04:00
Cardillan 73d5865908 Fix processor text/graphics buffer holding old content on restart (#12663) 2026-09-15 00:03:16 -04:00
NiTiSonandNiTiSon f474eab926 fix: Renderer update cause blocks to lose their extra and floor data (#12664)
Co-authored-by: NiTiSon <NiTiSon@users.noreply.github.com>
2026-09-15 00:03:02 -04:00
Anuken 0bcc96b5a2 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-09-14 10:57:02 -04:00
Anuken b76147ec50 Antialias + linear filter bleed on data patch images 2026-09-14 10:48:08 -04:00
Anuken 22ca0ce33f Avoidance radius clamp 2026-09-13 22:53:38 -04:00
Anuken 4368c6e60e Fixed #12657 2026-09-13 21:20:47 -04:00
Anuken 7591c51b60 More dummy validation + Pathfinder fixes 2026-09-13 21:15:29 -04:00
Anuken fb4bddd163 Support for dynamically-generated rounded/angled corners in UI 2026-09-13 20:23:30 -04:00
Anuken 5c7cacaafe Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-09-13 09:51:01 -04:00
Anuken 9c7b0981a6 Schematic reading simplification 2026-09-13 09:50:52 -04:00
Anuken 93c88fea8c Merge remote-tracking branch 'origin/master' 2026-09-13 09:15:04 -04:00
Anuken 9de4deed37 Fixed redundant mod browser mod icons being cached 2026-09-13 09:14:58 -04:00
Thinker8832 254fd3e28d Fix typo in split.container description (#12651) 2026-09-12 23:46:25 -04:00
EggleEgg 9a886aa582 Bugfix: overdriable dummy sddeq3e (#12653) 2026-09-12 23:46:09 -04:00
Anuken a51047a80d Merge remote-tracking branch 'origin/master' 2026-09-12 23:45:59 -04:00
Anuken 55dba0c156 Fixed #12650 2026-09-12 23:45:53 -04:00
WMF a98a7ba227 yet another requiredPlanets fix (#12649) 2026-09-12 23:28:09 -04:00
Anuken 56348b3e31 Fixed #12652 2026-09-12 23:21:40 -04:00
Anuken 89527f879b Fixed #12632 2026-09-12 12:41:42 -04:00
Anuken 57221d4a9f Merge remote-tracking branch 'origin/v9' into v9 2026-09-12 12:30:52 -04:00
Anuken 7f982b303b Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-09-12 12:30:31 -04:00
Anuken 78646f512e Made small data patch sounds load as one-shot wavs instead of streams 2026-09-12 11:50:15 -04:00
Anuken fd4eac0f81 Merge remote-tracking branch 'origin/master' 2026-09-12 11:00:55 -04:00
Anuken 60cc6a1839 Fixed #12647 2026-09-12 11:00:48 -04:00
Cardillan 51561bcb85 Allow ucontrol deconstruct in campaign (#12628) 2026-09-12 10:55:24 -04:00
summoner 3d56fefb51 Translation: Update bundle_hu.properties (#12637)
Translate new strings
Follow the changes of the english bundle
2026-09-12 10:55:02 -04:00
EggleEgg 9b7556a078 No hasItems for generic crafters 2026-09-12 10:54:47 -04:00
Github Actions cf2f3f82b5 Automatic bundle update 2026-09-12 14:54:29 +00:00
Александр Голомшток 3be43b1a54 Add sort-by-recently-played option to the map list (#12638)
* Add sort-by-recently-played option to the map list

The existing "recent" sort orders by the map file's last-modified
time, which only reflects edits - built-in maps never touch their
file, so it's meaningless for them, and for custom maps it tracks
last edited, not last played.

Track an actual last-played timestamp per map, the same way
high scores are already tracked (Core.settings, keyed by filename),
updated whenever a map finishes loading successfully outside of
playtesting. Add it as a fifth MapPriority option alongside the
existing four.

Resolves Anuken/Mindustry-Suggestions#5115

* Use eyeSmall icon per review feedback
2026-09-12 10:53:42 -04:00
Anuken a5c178ae5a Merge remote-tracking branch 'origin/master' 2026-09-12 10:49:51 -04:00
Anuken 06163708bd Fixed misleading build UI for team-specific infinite resources 2026-09-12 10:49:45 -04:00
Александр Голомшток 1ee9684d96 Leave sinking wreckage when units die over liquids (#12633) 2026-09-12 10:37:17 -04:00
Github Actions 137c6201c0 Automatic bundle update 2026-09-12 14:37:17 +00:00
redloong a341cff83f Refine Chinese translations in bundle_zh_CN.properties (#12631)
* Refine Chinese translations in bundle_zh_CN.properties

Updated various translations in the properties file for improved clarity and accuracy.

* Update Chinese localization for various labels

* Rename animated water settings to dynamic effects

Updated animated water settings to reflect dynamic effects.

* Update Chinese translations in bundle_zh_CN.properties
2026-09-12 10:36:26 -04:00
Anuken 7501697f02 Fixed #12644 2026-09-12 10:36:11 -04:00
Anuken 776214f7bb Merge remote-tracking branch 'origin/master' 2026-09-12 10:04:50 -04:00
Anuken 6df25c8308 Reverted fix for #12223 2026-09-12 10:04:44 -04:00
Cardillan ab51304dd6 Fixes #12640: Unset keybinding not saved (#12641) 2026-09-12 10:01:41 -04:00
Anuken e751e240db Fixed #12636 2026-09-12 09:59:07 -04:00
Anuken f490ce4a82 Removed sortPlans call 2026-09-11 21:04:48 -04:00
Anuken b0a3e52aad Removed deprecated fields/methods 2026-09-11 15:03:04 -04:00
Anuken 0a4d1a7fe7 Fixed default schematic size offset 2026-09-11 14:56:12 -04:00
Anuken fd11c61292 Fixed objective loading 2026-09-11 14:53:42 -04:00
Anuken 240d7667f6 Removed default loadout from generator 2026-09-11 14:50:26 -04:00
Anuken 1a34b786a7 Merge remote-tracking branch 'origin/v9' into v9 2026-09-11 12:59:31 -04:00
Anuken b7f1681157 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-09-11 12:58:55 -04:00
Anuken e675535cb7 Fixed fetch instruction layout 2026-09-11 03:02:08 -04:00
Anuken 84cdf2bbfe Fixed heal beam discontinuity 2026-09-11 02:40:28 -04:00
Anuken 6f4914d5cb arc 2026-09-11 01:56:19 -04:00
Anuken c7945610ee More dummy value validation 2026-09-11 01:50:09 -04:00
Anuken c6512c0b00 Fixed #12626 (by disallowing dummies in payloads) 2026-09-11 01:38:27 -04:00
Anuken cc5a63109a SoundControl crash fix 2026-09-11 00:56:38 -04:00
Anuken 43aa0d95f5 Closes Anuken/Mindustry-Suggestions/issues/6541 2026-09-11 00:49:24 -04:00
Anuken 42ad617bbd Temporary workaround for some mods crashing 2026-09-11 00:45:34 -04:00
Anuken e433d5f334 Fixed #11477 causing particle effects to be twice as big 2026-09-11 00:41:00 -04:00
Anuken 0ac15152d8 Fixed iOS crash 2026-09-10 21:02:40 -04:00
Anuken 4af4824ad0 arc 2026-09-10 20:29:29 -04:00
Anuken 83b93eafbb Don't animate conveyors in editor 2026-09-10 20:14:11 -04:00
Anuken 7f8f08d2c5 Merge remote-tracking branch 'origin/master' 2026-09-10 20:07:39 -04:00
Anuken 85e6db44c1 Map submission updates 2026-09-10 20:07:32 -04:00
Github Actions b430eaa239 Automatic bundle update 2026-09-11 00:01:29 +00:00
Александр Голомшток 889c581d73 Add descriptions for all logic sensor choices (#12622)
Only about 15 of the ~75 senseable LAccess values had a bundle entry, so
the rest fell through LCanvas.tooltip() (which has no lenum.* fallback for
them) and showed no tooltip on hover/long-press in the sensor picker.
A few also resolved to an unrelated lenum.* string of the same name -
for example @building showed "Building in a specific group".

Add a laccess.<name> line for every remaining senseable value, including
the privileged camera sensors, worded from the sense() implementations in
BuildingComp / UnitComp / BulletComp and the turret blocks.

Closes Anuken/Mindustry-Suggestions#5222
2026-09-10 20:00:11 -04:00
Anuken 6163278161 Merge remote-tracking branch 'origin/master' 2026-09-10 19:59:56 -04:00
Anuken ae9bb643e4 Closes #12624 2026-09-10 19:59:49 -04:00
Github Actions 2af44b5f5e Automatic bundle update 2026-09-10 23:52:49 +00:00
redloong 00ee86a1b7 fix for bundle (#12621)
* new

* Translate 'seconds' to '秒' in properties file
2026-09-10 19:51:59 -04:00
Sunky.MP3G 9e4d2e67d2 (WIP) RU translations (#12614)
* Wip translations

* Should be it

* small warning

* Typo

* Boss radar line

* Same for en

* `jump` fix
2026-09-10 19:51:28 -04:00
Anuken 34fa2bc52a Merge remote-tracking branch 'origin/master' 2026-09-10 19:51:13 -04:00
Anuken da4be8f848 Fixed #12623 2026-09-10 19:51:06 -04:00
Github Actions acd8682f40 Automatic bundle update 2026-09-10 23:37:35 +00:00
phinner 0e3ca1d2c6 French Translation: Just In Time... (#12625)
* french translation (pass 1)

* machine translation + ai

* french translation (pass 2)

* automated corrections + manual corrections

* french translation (pass 3)

* final manual corrections + consistency tweaks

* Prefer plurals
2026-09-10 19:36:51 -04:00
Github Actions 7c5f29e6fb Automatic bundle update 2026-09-10 15:45:35 +00:00
summoner 760fcb2e23 Translation: Update bundle_hu.properties (#12612)
* Translation: Update bundle_hu.properties

Translate new string
Follow the changes of the english bundle
Fix coherence
Fix line wrapping

* Translation: Update bundle_hu.properties

Follow the changes of the english bundle

* Translation: Update bundle_hu.properties

Follow the changes of the english bundle
2026-09-10 11:44:54 -04:00
Kevin VilyanandAnuken ded8eb762f Update Bundle ID + Fixed Main Bundle (#12617)
* Bundle ID Major Fixes

* lil

* gahhh,

* Add missing string + fixed "Jump" Token

* add  radartarget.label.boss  line

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-09-10 11:44:33 -04:00
Anuken ef5d3cb26b Fixed logic localization PR issues 2026-09-10 11:43:51 -04:00
Anuken b3317f3d4d Fixed #12620 2026-09-09 19:57:43 -04:00
Anuken 63b2069e96 Merge remote-tracking branch 'origin/master' 2026-09-09 18:10:41 -04:00
Anuken 52232dc2ee Fixed print statement field width 2026-09-09 18:10:35 -04:00
Github Actions 961e8b6e60 Automatic bundle update 2026-09-09 21:56:59 +00:00
Anuken d0048f32de Merge fixes 2026-09-09 17:55:43 -04:00
Anuken 867dd29ba8 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/assets/bundles/bundle_es.properties
#	core/assets/bundles/bundle_it.properties
#	core/src/mindustry/game/MapObjectives.java
#	core/src/mindustry/logic/LExecutor.java
#	core/src/mindustry/world/blocks/payloads/PayloadMassDriver.java
#	gradle.properties
#	tests/src/test/java/ApplicationTests.java
2026-09-09 17:51:03 -04:00
Github Actions 64bc6d3ac0 Automatic bundle update 2026-09-09 16:47:29 +00:00
Anuken 124dcc67aa Merge remote-tracking branch 'origin/master' 2026-09-09 12:46:48 -04:00
Anuken 2276f471f2 Merge branch 'logic-editor-autowrap'
# Conflicts:
#	core/src/mindustry/logic/LStatements.java
2026-09-09 12:45:27 -04:00
Anuken 2837f2cad2 More layout fixes 2026-09-09 12:43:04 -04:00
Anuken 6407a48973 Major cleanup of layout 2026-09-09 11:20:20 -04:00
Cardillan f02d919b64 Properly compute UTF16 sizes for escapes (#12616) 2026-09-09 10:17:14 -04:00
Anuken 5566674c29 Fixed #12615 2026-09-09 10:15:55 -04:00
Anuken 80a99eb031 More UI fixes 2026-09-09 09:07:37 -04:00
Anuken cfe01850aa UI bugfixes 2026-09-09 08:51:33 -04:00
Anuken 48158883c1 Fixed inconsistent search bar in rules 2026-09-08 23:41:14 -04:00
Anuken d71be5ecb1 Fixed #12613 2026-09-08 17:57:31 -04:00
Anuken 1ba71a14f7 Merge remote-tracking branch 'origin/master' 2026-09-08 10:10:57 -04:00
Anuken 12157feeca Logic \uXXXX escape support 2026-09-08 10:10:48 -04:00
Github Actions 200f4d42be Automatic bundle update 2026-09-08 06:42:43 +00:00
EggleEgg 201f606383 Crucible output scales with attribute boost (#11552) 2026-09-08 02:42:02 -04:00
Anuken cf8b1c6b34 Escape round-trip fix 2026-09-08 02:29:31 -04:00
Anuken 04452e6ba8 Logic parser improvements for quote/escape handling + unit tests 2026-09-08 01:35:36 -04:00
Anuken 9ca00b5935 Merge remote-tracking branch 'origin/master' 2026-09-08 01:01:41 -04:00
Anuken 05999c9759 Pathfinding fixes 2026-09-08 01:01:34 -04:00
Jason d23f113806 update allure to latest commit (#12610) 2026-09-07 22:21:00 -04:00
Anuken cc36b51bad Fixed #12611 2026-09-07 22:20:32 -04:00
Anuken 3787b6308c minor tweaks 2026-09-07 19:32:15 -04:00
Anuken 7e2d57247d minor tweaks 2026-09-07 14:25:41 -04:00
Anuken 80a2eef239 Removed row() 2026-09-07 14:17:48 -04:00
Anuken 16ee499f75 Longer fields, width cap 2026-09-07 13:55:49 -04:00
Anuken a9ff32df12 Merge branch 'master' of https://github.com/Anuken/Mindustry into logic-editor-autowrap
# Conflicts:
#	gradle.properties
2026-09-07 13:37:49 -04:00
Anuken 37c1b6ac1e Merge remote-tracking branch 'origin/master' 2026-09-07 13:01:55 -04:00
Anuken 54e5f3bcf6 Reduced standard conveyor to 5 items/sec (https://github.com/Anuken/Mindustry/pull/12369#issuecomment-4984396153) 2026-09-07 13:01:41 -04:00
Vector 2290685999 Update bundle_es.properties (#12455)
* Update bundle_es.properties

* Update bundle_es.properties

* Atolls tutorial

* Frozen Forest tutorials

Updated Spanish translations for various game mechanics and instructions.

* Scathe ammo

* Update bundle_es.properties

* logic strings

* Update bundle_es.properties

* some settings translations

* Update bundle_es.properties

* Update bundle_es.properties

* there we go

* locale config

* test

* ucontrol test

Updated Spanish translations for various labels and objectives.

* target dummy

* Update bundle_es.properties

* Update bundle_es.properties

sensor and effect translations

* Update bundle_es.properties

* Update bundle_es.properties

* Update bundle_es.properties
2026-09-07 12:43:56 -04:00
Anuken f3cbb54af5 Merge remote-tracking branch 'origin/master' 2026-09-07 12:41:19 -04:00
Anuken 85446f3284 Fixed unit movement regression caused by #11613 / Alternate unit mining effect (closes #12605) 2026-09-07 12:41:05 -04:00
Jason ba93ccfc3e update Allure to an archive public repo (#12607)
* update Allure to an archive public repo

* updated SHA

Signed-off-by: Jason <131086642+JasonP01@users.noreply.github.com>

---------

Signed-off-by: Jason <131086642+JasonP01@users.noreply.github.com>
2026-09-07 12:35:53 -04:00
EggleEgg a1e7aad19d Bugfix: show random lightning length in corvus stats (#12606) 2026-09-07 12:35:41 -04:00
redloong 9d07ba06ab Update unbindKey translation to '解绑' (#12608) 2026-09-07 12:19:29 -04:00
Anuken 5a0c4bfc41 Texture streaming Android compat fix 2026-09-06 17:03:39 -04:00
Anuken 58ed13fc96 Mining color alternative 2026-09-06 16:19:42 -04:00
Anuken 1f6c9eac65 Fixed wiki crash 2026-09-06 12:23:14 -04:00
Anuken bf3d400ca5 Merge remote-tracking branch 'origin/master' 2026-09-06 10:48:44 -04:00
Anuken e37c2f1ec2 Fixed #12603 2026-09-06 10:48:38 -04:00
Github Actions d95a3ef6aa Automatic bundle update 2026-09-06 14:39:33 +00:00
JniTrRny c2f7bddb0f Update bundle_th.properties (#12599)
* quick update

* 2much2translate
2026-09-06 10:38:42 -04:00
Anuken ec656a63eb Merge remote-tracking branch 'origin/master' 2026-09-06 10:38:03 -04:00
Anuken 06f2dc7032 Fixed #12600 2026-09-06 10:37:54 -04:00
summoner 0e5189e1b7 Translation: Update bundle_hu.properties (#12601)
* Translation: Update bundle_hu.properties

Translate new strings
Fix translation

* Translation: Update bundle_hu.properties

Fixing line wrapping
fix wording
2026-09-06 10:32:42 -04:00
Cardillan c477c767c5 Make the Back button first in the keybind dialog (#12604) 2026-09-06 10:32:35 -04:00
Anuken c81d0eb025 Merge remote-tracking branch 'origin/master' 2026-09-05 16:14:42 -04:00
Anuken 7494e9a1a8 Update bundle_id_ID (#12580) 2026-09-05 16:14:34 -04:00
Github Actions ccf6b81ed6 Automatic bundle update 2026-09-05 20:12:11 +00:00
summoner 171899596f Translation: Update bundle_hu.properties (#12592)
* Translation: Update bundle_hu.properties

Translate new strings

* Translation: Update bundle_hu.properties

Translate new strings

* Fix translation

Fix translation
2026-09-05 16:11:24 -04:00
Anuken 953c58fc49 Mod description wrap fix 2026-09-05 16:11:00 -04:00
Github Actions ec4fe559f5 Automatic bundle update 2026-09-05 20:04:57 +00:00
Cardillan 8079274531 Allow selecting a version when reinstalling a mod (#12589)
* Mod reinstall select version

* Support for JSON mods with/without releases

* Removed commented-out code
2026-09-05 16:04:23 -04:00
Anuken ca3c0f30b8 Fixed tests 2026-09-05 14:09:24 -04:00
Anuken a7955970ff Fixed some map multipliers 2026-09-05 12:49:40 -04:00
Anuken dbbd03f4cd Merge remote-tracking branch 'origin/master' 2026-09-05 12:39:13 -04:00
Anuken 788ead37fb Fixed #12598 2026-09-05 12:39:06 -04:00
Github Actions 83dd62f2ad Automatic bundle update 2026-09-05 13:52:41 +00:00
Cardillan 5ee6debb2a Restore failed mod indicator (#12596) 2026-09-05 09:51:52 -04:00
redloong 07a080931d Something to fix (maybe?) (#12595)
* Update cutsceneaction.label.active to 'active'

* Update translations in bundle_zh_CN.properties

Updated translations for dynamic effects and markers.

* Modify Chinese translations for UI elements

Updated translations for dynamic effects and target dummy.

* Translate prioritize filter labels to Chinese

* new
2026-09-05 09:51:27 -04:00
Anuken 0c44604a0f Fixed overgrowth rules 2026-09-05 09:43:07 -04:00
Anuken a9dfed098a Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-09-05 09:41:26 -04:00
Anuken 71aa9230bf arc 2026-09-05 09:41:23 -04:00
EggleEgg 666978f9e1 foos will probably bypass this (#12594) 2026-09-04 18:13:02 -04:00
EggleEgg 9fe9344dfd Disallow conveyor bridge/phase bridge from accepting items when disabled (#12585)
* Disallow conveyor bridge/phase bridge from accepting items when disabled

* re23rwsdwed
2026-09-04 12:14:29 -04:00
Anuken f2e1e2ad4f Initial network entity sync fixes 2026-09-04 11:28:17 -04:00
Anuken ca6b369b85 Grouped targeting (closes #11537) 2026-09-03 19:02:51 -04:00
Anuken ef65b1f5b3 Merge remote-tracking branch 'origin/master' 2026-09-03 17:50:06 -04:00
redloong 962a3d859f Update bundle_zh_CN (#12584)
* Update cutsceneaction.label.active to 'active'

* Update translations in bundle_zh_CN.properties

Updated translations for dynamic effects and markers.

* Modify Chinese translations for UI elements

Updated translations for dynamic effects and target dummy.

* Translate prioritize filter labels to Chinese
2026-09-03 17:50:03 -04:00
Anuken daf36fc2a2 Removed redundant option 2026-09-03 17:49:59 -04:00
EggleEgg 52a10f6898 Bugfix: Fix target dummy velocity upon knockback under lower fps (#12588) 2026-09-03 17:48:49 -04:00
Github Actions a8b1dda1a1 Automatic bundle update 2026-09-03 14:05:58 +00:00
Anuken dbd527dbdf Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-09-03 10:05:08 -04:00
Anuken ddbdfbb447 Merge branch 'cardillan-pr/unbind-keys-2' 2026-09-03 10:05:03 -04:00
Anuken fda8db5562 Fixed ; 2026-09-03 10:05:00 -04:00
Github Actions b515773fbf Automatic bundle update 2026-09-03 14:03:13 +00:00
redloong a5dc717ff9 Fix cutsceneaction.label.active value (#12583)
* Update cutsceneaction.label.active to 'active'

* Update translations in bundle_zh_CN.properties

Updated translations for dynamic effects and markers.
2026-09-03 10:02:35 -04:00
cardillan 13bc8aa881 Move the unset button to the keybind dialog 2026-09-03 10:35:26 +02:00
Anuken f958406e5e Closes Anuken/Mindustry-Suggestions/issues/6502 2026-09-02 23:06:39 -04:00
Anuken 3ebd0c9f4f Merge remote-tracking branch 'origin/master' 2026-09-02 22:01:11 -04:00
Anuken 66e47fdc57 Fixed typo 2026-09-02 22:00:47 -04:00
Github Actions 33bc4c9e6f Automatic bundle update 2026-09-03 01:40:21 +00:00
Anuken a360416946 Better map sorting/filter system (Closes #12349) 2026-09-02 21:39:38 -04:00
Anuken 95f600e87a Merge remote-tracking branch 'origin/master' 2026-09-02 19:09:48 -04:00
Anuken c492376c87 Reduced rotation speed of several larger serpulo turrets to be less ridiculous 2026-09-02 19:09:18 -04:00
SomeonesShade 53b9d15993 Arc Changes and Adding PierceCap for Lightning (#11768) 2026-09-02 18:49:07 -04:00
Anuken 115551b4f4 Merge remote-tracking branch 'origin/master' 2026-09-02 17:48:04 -04:00
Anuken 9e95a4bbc4 No lightning status chance 2026-09-02 17:47:58 -04:00
Github Actions fa59008448 Automatic bundle update 2026-09-02 21:02:23 +00:00
Anuken a298ccfd45 Merge branch 'JasonP01-statusChance' 2026-09-02 17:01:40 -04:00
Anuken ee6c9ae1ab Merge branch 'statusChance' of https://github.com/JasonP01/Mindustry into JasonP01-statusChance 2026-09-02 17:01:37 -04:00
Anuken 8238b9d2c1 Merge remote-tracking branch 'origin/master' 2026-09-02 16:33:14 -04:00
Anuken 49dbd44604 PR Cleanup 2026-09-02 16:33:07 -04:00
Github Actions 553c2beeea Automatic bundle update 2026-09-02 20:32:14 +00:00
CardillanandAnuken 7c0f19a520 Allow automatically disabled mods to be restored (#12263)
* Allow automatically disabled mods to be restored

* Indicate failed status

* Apply suggestion from @Anuken

* Update bundle.properties

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-09-02 16:31:31 -04:00
Github Actions cbf0025712 Automatic bundle update 2026-09-02 20:22:52 +00:00
summoner 5af84b4ad5 Translation: Update bundle_hu.properties (#12575)
Translate new strings
fix translation
2026-09-02 16:22:08 -04:00
redloong 0bb475a54d Translation: Update bundle_zh_CN.properties (#12578) 2026-09-02 16:22:00 -04:00
Anuken db8d9669c2 Fixed #12579 2026-09-02 16:21:26 -04:00
Anuken f7ededb3a1 Removed server list tests 2026-09-02 13:05:13 -04:00
Anuken 69257a2eb4 Removed legacy server lists
(There was only one server group online for v7, and it had 0 players)
2026-09-02 12:58:56 -04:00
Anuken 2b3fee983c Fixed bugs related to invalid overlay floors + map colors 2026-09-02 12:46:15 -04:00
Anuken e4045fb8a5 Merge remote-tracking branch 'origin/master' 2026-09-02 10:24:40 -04:00
Anuken 6ef175cb29 Building afterReadAll fix + Send entities over network (possibly unstable) 2026-09-02 10:24:31 -04:00
SITUVNgcd 63e839c67c Fixed campaign.rework.serpulo invisible characters (#12574) 2026-09-02 09:52:47 -04:00
Anuken ccae400bcf Stealing from foos but done properly 2026-09-02 09:48:58 -04:00
JasonP01 dc75f996b0 Merge upstream/master into statusChance 2026-09-02 02:41:19 +02:00
JasonP01 e567777179 revert testing values, and fix stat render 2026-09-02 02:36:14 +02:00
Anuken 667907009d Merge remote-tracking branch 'origin/master' 2026-09-01 20:20:28 -04:00
Anuken b9189a5570 LAccess cleanup 2026-09-01 20:20:21 -04:00
Eric W.andAnuken fac33d08d7 allow memory blocks to store any object (#12459)
* allow memory blocks to store any object

This changes the way memory blocks are stored in save files.

* fix memory block contents not being restored

`afterReadAll()` seems to require `update` being set to `true`
for being called.

* add myself as a contributor

* reduce boxing when reading/writing memory buildings

This includes some changes to `TypeIO` to prevent
duplicating its reading/writing logic.

* Update TypeIO.java

* Update MemoryBlock.java

* Update TypeIO.java

* Apply suggestion from @Anuken

* Apply suggestion from @Anuken

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-09-01 20:18:03 -04:00
JasonP01 182db13909 fix? stat value 2026-09-02 02:17:48 +02:00
EggleEgg d2ee7cdf42 Bugfix: laserbolt pierces plast walls (#12573)
* Bugfix: laserbolt pierces plast walls

* whether ugh
2026-09-01 19:59:09 -04:00
Github Actions cf41adda2b Automatic class mapping and map name update 2026-09-01 23:55:33 +00:00
Github Actions 5720f8b9b6 Automatic bundle update 2026-09-01 23:54:40 +00:00
Anuken b8917ff608 Merge branch 'EggleEgg-dps-dummy' 2026-09-01 19:53:57 -04:00
EggleEgg b3e8aa9294 more or less. Still missing engines
done I think?

applied revisions from jason

okay should be enough fallbacks

better team getter

dont use multiple configs under saveConfig, the game does not like that

Minor tweaks to DPS dummy
2026-09-01 19:53:26 -04:00
JasonP01 69cb000395 fix chance in remote places 2026-09-02 01:13:48 +02:00
JasonP01 e115a4a0a0 fix stat values 2026-09-02 00:40:20 +02:00
JasonP01 01fcc9d674 Merge branch 'statusChance' of https://github.com/JasonP01/Mindustry into statusChance 2026-09-02 00:05:46 +02:00
JasonP01 664b7a3e45 update to comply 2026-09-02 00:05:39 +02:00
JasonP01 aeba3e1f63 Merge remote-tracking branch 'upstream/master' into statusChance 2026-09-01 23:20:43 +02:00
Anuken 27d7a2917e Merge remote-tracking branch 'origin/master' 2026-09-01 17:18:41 -04:00
Anuken 023a4ff1ae Fixed logic privileged access check 2026-09-01 17:18:34 -04:00
SomeonesShade 7509cb1375 Nova Buff (#11769)
* Nova Changes v3

* merging from egglegg

* Removed randomTimer

* Adjusted Nova Stats

* That reload change wasn't a good idea

* Nova Heal Rate nerf (15 hp/s -> 10 hp/s) same inter-nova heal and Hp nerf (240 -> 200 hp)

* Nerfed Nova DPS (2x32.5 -> 2x26)
 Lowered smart downtime for novas
2026-09-01 16:54:58 -04:00
Github Actions bc3a701b93 Automatic bundle update 2026-09-01 20:51:26 +00:00
Anuken 6be1d664b0 Merge branch 'summoner001-master' 2026-09-01 16:50:45 -04:00
Anuken aa929b9c61 Merge branch 'master' of https://github.com/summoner001/Mindustry into summoner001-master 2026-09-01 16:50:37 -04:00
Github Actions 2504e6a93c Automatic bundle update 2026-09-01 20:50:26 +00:00
redloong 0d5c83f928 Make #12158 feature toggleable (#12569) 2026-09-01 16:49:47 -04:00
EggleEgg 79c314a983 Bugfix: maxHealth sort ui clipping (#12572) 2026-09-01 16:45:36 -04:00
Alone 0352ae9bf3 Improved banned and patched content indicators in the database (#12570) 2026-09-01 11:29:06 -04:00
Anuken ae291be0a1 Fixed #12565 2026-09-01 11:26:28 -04:00
Anuken 7e80948b58 Merge remote-tracking branch 'origin/master' 2026-09-01 11:11:58 -04:00
Anuken dcc54faa93 Fixed #12566 2026-09-01 11:11:51 -04:00
Sunky.MP3G 1f5fe1ae13 Duct caps (#12568) 2026-09-01 11:05:01 -04:00
summoner 6deaea5356 Translation: Update bundle_hu.properties
Translate new strings
Fix coherence
Follow the changes of the english bundle
2026-09-01 16:20:53 +02:00
Github Actions 7f009df50f Automatic bundle update 2026-09-01 02:14:53 +00:00
Anuken e69d827f72 Merged #12158 2026-08-31 22:14:02 -04:00
Github Actions b4cd02137d Automatic bundle update 2026-09-01 02:03:49 +00:00
Anuken f7f002b786 Merge remote-tracking branch 'origin/master' 2026-08-31 22:03:11 -04:00
Anuken 2564190ae3 Fixed duplicate bundle key 2026-08-31 22:03:04 -04:00
Efsfse2280 6732c14779 High Tier Armor Buffs+Spiroct (#12027)
* Update UnitTypes.java

* edit

* spiroct lifesteal counternerf

* milder values for now

* final

* keep arkyid HP
2026-08-31 21:44:42 -04:00
Github Actions 76877127b8 Automatic class mapping and map name update 2026-09-01 01:17:29 +00:00
Sunky.MP3G 6cccf21960 Improved Basin missile and fixed markers (#12348) 2026-08-31 21:16:13 -04:00
Anuken b934bfc4f1 Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-08-31 21:08:15 -04:00
Anuken 25fe0cc9f9 Merge branch 'MEEPofFaith-improved-reactor-explosion' 2026-08-31 21:08:11 -04:00
Anuken 06d527a7ca Generator explosion tweaks 2026-08-31 21:08:01 -04:00
Anuken e386a2c85b Merge branch 'improved-reactor-explosion' of https://github.com/MEEPofFaith/Mindustry into MEEPofFaith-improved-reactor-explosion 2026-08-31 21:00:05 -04:00
42ce901da2 Balancing Payload Logistics: PMD, Assorted Changes, and Deconstructor Behavioral Changes (#12182)
* Payload Changes 3 (final)

* Deconstructor Behavior Changes Final

* Added full-storage icon

* adjustments

* removed fontello file

* Removed full-storage.png

* Tweaked itemBuffer

* Update IconConverter.java

* Apply suggestion from @Anuken

---------

Co-authored-by: EggleEgg <125359838+EggleEgg@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-31 20:57:06 -04:00
EggleEgg 616cc98098 Ability to see and grab what's inside of bridge blocks (#11605)
* just this

* swapConfigInventory

* fixed
2026-08-31 20:42:13 -04:00
Anuken 87c5e27f50 Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-08-31 20:40:29 -04:00
Anuken 3271d9d72e Merge branch 'EggleEgg-no-payload-conveyor-for-payenter' 2026-08-31 20:40:25 -04:00
Anuken 87d27b3070 PR bugfixes 2026-08-31 20:40:14 -04:00
Anuken df06d44c19 Merge branch 'no-payload-conveyor-for-payenter' of https://github.com/EggleEgg/Mindustry into EggleEgg-no-payload-conveyor-for-payenter 2026-08-31 20:25:54 -04:00
Github Actions 8b965dd872 Automatic bundle update 2026-09-01 00:19:43 +00:00
JniTrRny 01849ef1b3 Update bundle_th.properties (#12562) 2026-08-31 20:19:07 -04:00
summoner 0ac6fcca16 Translation: Update Hungarian.properties (#12563)
Translate new strings
Follow the changes of the english bundle
Fix translation coherence
2026-08-31 20:18:58 -04:00
Anuken c48b239de0 Fixed #12560 2026-08-31 20:18:02 -04:00
Anuken da3b3358cd Merge remote-tracking branch 'origin/master' 2026-08-31 10:11:05 -04:00
Anuken 8538190e80 Fixed research desc wrapping 2026-08-31 10:10:57 -04:00
Cardillan 4df53b8e04 Force display update when copying (#12418) 2026-08-30 16:17:00 -04:00
Github Actions 06dd6d98b2 Automatic class mapping and map name update 2026-08-30 20:14:59 +00:00
Anuken e87793968a Merge remote-tracking branch 'origin/master' 2026-08-30 16:13:23 -04:00
Anuken 0dcad1261c Fixed compilation 2026-08-30 16:13:17 -04:00
Bujandbuj d6fd7a0977 bullet create event (#11444)
Co-authored-by: buj <buj351@outlook.com>
2026-08-30 16:08:47 -04:00
Anuken 97a438cab3 Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-08-30 16:06:45 -04:00
Anuken 48e56fcd7b Merge branch 'EggleEgg-bridge-link-any' 2026-08-30 16:06:40 -04:00
Anuken 81e18df994 Merge branch 'bridge-link-any' of https://github.com/EggleEgg/Mindustry into EggleEgg-bridge-link-any 2026-08-30 16:06:36 -04:00
Github Actions 12d7492708 Automatic bundle update 2026-08-30 20:04:45 +00:00
efa856226d Add missing pt_BR (Brazilian Portuguese) localization (#11935)
* Add most of missing pt_BR localization strings

Still missing:
- sector descriptions (around lines 970)
- bullet/damage descriptions (around lines 1220)
- checking consistency on block names (around lines 1800)

* Apply suggestions from DinoWattz

Co-authored-by: DinoWattz <116862698+DinoWattz@users.noreply.github.com>

* Apply missing suggestions from DinoWattz

Co-authored-by: DinoWattz <116862698+DinoWattz@users.noreply.github.com>

* Update bullet/damage descriptions

---------

Co-authored-by: DinoWattz <116862698+DinoWattz@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-30 16:04:09 -04:00
Efsfse2280 3b0548d42e that's about it (for now) (#11765) 2026-08-30 15:58:31 -04:00
Github Actions cf4a69cb33 Automatic bundle update 2026-08-30 19:39:53 +00:00
Redstonneur1256andAnuken 37bf2d8c2d Allow markers to be used as light sources (#10762)
* Allow markers to be used as light sources

* Better light source markers

* Move PointMarker drawLight to LightMarker

* Add a rule for unit lights

* Optimize marker rendering

* Update core/assets/bundles/bundle.properties

* Fix compatibility with existing saves

* Fix incorrect light radius

* Apply suggestion from @Anuken

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-30 15:39:13 -04:00
Github Actions 66d80f8b8c Automatic bundle update 2026-08-30 19:27:37 +00:00
Anuken c3c231ff6c Merge remote-tracking branch 'origin/master' 2026-08-30 15:26:54 -04:00
Anuken 0de5cb7e6b Revert "init (#11355)"
This reverts commit e46deae1b1.
2026-08-30 15:26:37 -04:00
Github Actions 124640e23a Automatic bundle update 2026-08-30 19:24:25 +00:00
xX_404BrainNotFound_XxandAnuken e46deae1b1 init (#11355)
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-30 15:23:41 -04:00
Github Actions 19322f91f5 Automatic bundle update 2026-08-30 19:05:48 +00:00
SITUVNgcd 168dcb1dd2 Update Vietnamese translation (#12558)
https://github.com/Anuken/Mindustry/commit/b452ac48f74327f671929d22250eb92a1cd005cb
2026-08-30 15:05:03 -04:00
Pyratite No Lead 48978acc47 Update Simplified Chinese Translation (#12559) 2026-08-30 15:04:15 -04:00
Github Actions eb4d7f1de6 Automatic bundle update 2026-08-29 22:23:59 +00:00
笙歌andAnuken da16465961 Update zh_TW string (#12492)
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-29 18:23:15 -04:00
Anuken 25b42157a9 Merge remote-tracking branch 'origin/master' 2026-08-29 18:15:54 -04:00
Anuken 2fa2fc9bf1 Fixed potential crash 2026-08-29 18:15:48 -04:00
Github Actions b452ac48f7 Automatic bundle update 2026-08-29 22:04:58 +00:00
EggleEggandAnuken 0e956a1f8e More db entry qol (#12548)
* dammit

* stats.timePeriod disappeared huh

* Update bundle.properties

* Update bundle.properties

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-29 18:04:15 -04:00
Github Actions 460debfa0c Automatic bundle update 2026-08-29 22:03:10 +00:00
Anuken adbb931d93 Merge remote-tracking branch 'origin/master' 2026-08-29 18:02:28 -04:00
Anuken f4307e8db3 Bundle cleanup 2026-08-29 18:02:21 -04:00
Github Actions 60c35280f1 Automatic bundle update 2026-08-29 21:58:10 +00:00
DozhamandAnuken b843a50c4b Add more extensive descriptions for settings (bundle.properties) (#11335)
* Add more extensive descriptions for settings

* add/modify descriptions

* Update bundle.properties

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-29 17:57:34 -04:00
Github Actions 19544d1e51 Automatic bundle update 2026-08-29 21:29:28 +00:00
Anuken 8b4cf3e3be Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-08-29 17:28:43 -04:00
Anuken 8824d36dd2 Merge branch 'giannir1988-master' 2026-08-29 17:28:39 -04:00
Anuken ea7a69c637 Merged 2026-08-29 17:28:37 -04:00
spentcud cb3fd27cce navanax dmg buff (#12189) 2026-08-29 17:26:34 -04:00
Facundo Esteban Lemo 6e19c7e6e5 [TRANSLATION] Steam page and achievements to Spanish and Latam Spanish. (#11288)
* spanish steam page

* latam spanish steam page
2026-08-29 17:24:46 -04:00
summoner be25b94242 Translataion: Update bundle_hu.properties (#12551)
Translate new strings
2026-08-29 14:40:43 -04:00
Anuken d16ec09793 Fixed #12549 2026-08-29 14:39:38 -04:00
Anuken 8041a9de3f var 2026-08-29 13:44:54 -04:00
Anuken eeeec99215 Merge remote-tracking branch 'origin/v9' into v9 2026-08-29 09:57:41 -04:00
Anuken 854a71eb32 Removed deprecated methods 2026-08-29 09:57:31 -04:00
Anuken 22f0b9a5c7 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/logic/LExecutor.java
#	core/src/mindustry/world/blocks/logic/LogicDisplay.java
#	core/src/mindustry/world/meta/StatValues.java
#	gradle.properties
2026-08-29 09:53:28 -04:00
Anuken 4db3cd713c Merge remote-tracking branch 'origin/master' 2026-08-28 18:33:50 -04:00
Anuken 8553bb7ecc Revert "Fix mod browser null listing crash (#12546)"
This reverts commit 77e2ce7274.
2026-08-28 18:33:32 -04:00
Jason 12a22933dc Merge branch 'Anuken:master' into statusChance 2026-08-29 00:20:55 +02:00
Cardillan 9d49b58571 More tileable display fixes (#12514) 2026-08-28 18:15:49 -04:00
Anuken f29235ebf3 Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-08-28 18:11:48 -04:00
Anuken f761cdc79a Merge branch 'Adleanogare-dob_json' 2026-08-28 18:11:43 -04:00
Anuken a750252c02 Fixed PR 2026-08-28 18:11:31 -04:00
Github Actions 456adc6a4f Automatic bundle update 2026-08-28 21:46:47 +00:00
Anuken 89587e378b Merge remote-tracking branch 'origin/master' 2026-08-28 17:46:08 -04:00
Anuken 19186c677c Closes #12173 2026-08-28 17:46:02 -04:00
DinoWattz c1c4781f22 Add missing store localization for Brazilian Portuguese (#11743)
* Add steam translations

* Add google play translations

* Fix typo in achievement's name
2026-08-28 17:25:23 -04:00
EggleEgg db54e4f350 requested. Whoever wants this change fight for it. Good luck. (#11846) 2026-08-28 17:24:32 -04:00
Anuken 4be3f27d5c Merge remote-tracking branch 'origin/master' 2026-08-28 17:20:47 -04:00
Anuken a1975a40b6 Do not kill GL context on uiMode Android change 2026-08-28 17:20:40 -04:00
Pyratite No Lead 5112fb9a0e Update Simplified Chinese Translation (#12545)
* Update Simplified Chinese Translation

* Fix typo

* Update Simplified Chinese Translation

* Update Simplified Chinese Translation

* Update Simplified Chinese Translation
2026-08-28 17:19:08 -04:00
Anuken e2cecffec3 Fixed #12544 2026-08-28 17:18:43 -04:00
Anuken 3f65bdd383 Fixed #12541 2026-08-28 17:04:22 -04:00
Anuken 98cec2df46 Merge remote-tracking branch 'origin/master' 2026-08-28 16:54:29 -04:00
Anuken e6b66673a3 Fixed #12543 2026-08-28 16:54:22 -04:00
Github Actions 756439ce66 Automatic bundle update 2026-08-28 20:51:52 +00:00
EggleEgg 84b3c3d809 Account for liquid heat when extinguishing + more (#11664)
* Account for liquid heat when extinguishing + more

* always keep at least 1

* use a gamerule instead

* team changer gamerule

* typo + rename

* use baseteams e340'ri3490turgw4
2026-08-28 16:50:57 -04:00
EggleEgg 332cd6d118 some adjustments for #12527 just in case (#12540) 2026-08-28 16:50:32 -04:00
ZenthXSin 77e2ce7274 Fix mod browser null listing crash (#12546)
* Fix mod browser null listing crash

* Fix lambda capture after null list fallback
2026-08-28 16:50:14 -04:00
EggleEgg 6ed7a905a4 recon stance 2026-08-28 03:02:18 +02:00
Anuken f92db080ed Merge remote-tracking branch 'origin/master' 2026-08-27 18:45:45 -04:00
Anuken 02dea62c26 Fixed #12539 2026-08-27 18:45:38 -04:00
Github Actions dc32943612 Automatic class mapping and map name update 2026-08-27 16:46:49 +00:00
Vladislav SuchkovandAnuken e981ce8faf Add more spacing to map objectives (#11790)
* add spacing

* more line break

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-27 12:44:54 -04:00
WMF 0699ae305e new event™️ (#11827) 2026-08-27 12:44:21 -04:00
Github Actions 2ebd548170 Automatic class mapping and map name update 2026-08-27 16:37:22 +00:00
Rylid-UmilandAnuken b05d9a11f1 Add lifeRnd and extraLife for Weapons and more (#11477)
* lifeRnd and extraLife

like velocityRnd and extraVelocity but with bullet lifetimes. random is applied before the scaling with scaleLife.

* Update contributors

* particle aspect ratio system

* fix bug

* seperate fin and color fin

* Update ParticleEffect.java

* New Triangle effect 

i'm trying my best bro

* ok i found the bug and i fixed it

* bug squashed 2

* addede extraLife and lifeRnd, and extraVelocity for turrets

* Okay okay, one last change.

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-27 12:34:23 -04:00
Anuken e488a79096 Merge remote-tracking branch 'origin/master' 2026-08-27 12:31:11 -04:00
Anuken 428785494d Fixed input handler switch not updating quadtrees 2026-08-27 12:31:04 -04:00
DeterMination 7efe3b2ea7 Increase map editor undo history limit (#12536) 2026-08-27 12:12:27 -04:00
Github Actions 25bc99c68b Automatic class mapping and map name update 2026-08-26 20:59:40 +00:00
Anuken 2b9937c3be arc 2026-08-26 16:56:24 -04:00
Anuken 9f0bd7f579 Allow world processors to configure + sense bridges/nodes/mass drivers
Replaces & closes #11503
2026-08-26 16:55:10 -04:00
Anuken 3267830fc9 More drill rendering fixes post-PR 2026-08-26 15:38:49 -04:00
Anuken 309f56b108 Drill rim rendering tweaks 2026-08-26 15:35:06 -04:00
Anuken 684c840080 Fixed drill rim rendering 2026-08-26 15:33:02 -04:00
Anuken 72d5df4c75 Compile fix 2026-08-26 15:25:40 -04:00
85654ee544 Give Drill type drawers (#10524)
* Give Drill type drawers

* quick style fix

* reversal whups

* Allow legacy rim

* quick

* Fix preview generation leaking buildings into world (#12511)

This wasn't ever noticed before but now that world logic can do crazy stuff, it causes a lot of issues.

* Add armor value access to Block and BuildingComp (#12510)

* Fixed #12509

* Fixed #12512

* Fix PlacementFragment at large ui scales. (#12515)

* Fixed save load text wrapping

* Update bug_report.yml

* Call afterDestroyed method on build in destroyed() (#12525)

* Fixed 'escelating' objective typo in existing saves

* Removed camera sensors from non-privileged logic

* Qol: .info descriptions to unit weapons (#12527)

* Fixed #12531

---------

Co-authored-by: buthed010203 <naguiar010203@gmail.com>
Co-authored-by: Kaleinova <160325865+Kaleinova@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
Co-authored-by: MCxzfwq <mcxzfwq@outlook.com>
Co-authored-by: EggleEgg <125359838+EggleEgg@users.noreply.github.com>
2026-08-26 15:20:53 -04:00
Anuken 894bab4ecd Merge remote-tracking branch 'origin/master' 2026-08-26 15:17:09 -04:00
Anuken d69229a333 Fixed #12531 2026-08-26 15:17:01 -04:00
EggleEgg 7ecd2f4249 Qol: .info descriptions to unit weapons (#12527) 2026-08-26 15:06:22 -04:00
Anuken 17f3d89300 Removed camera sensors from non-privileged logic 2026-08-26 15:00:48 -04:00
Anuken 82ac6a98a5 Fixed 'escelating' objective typo in existing saves 2026-08-26 09:36:24 -04:00
Anuken 5da3bbd414 Merge remote-tracking branch 'origin/v9' into v9 2026-08-26 09:32:20 -04:00
Anuken 3f40c250d3 Switched to .hjson for texture packer config 2026-08-26 09:32:08 -04:00
MCxzfwq 27ba9d7cd2 Call afterDestroyed method on build in destroyed() (#12525) 2026-08-24 03:10:18 -04:00
Anuken 0194398a81 Update bug_report.yml 2026-08-22 05:04:38 -04:00
Anuken a4974ec8e3 Merge remote-tracking branch 'origin/master' 2026-08-20 09:43:13 +02:00
Anuken 3086ea6ecf Fixed save load text wrapping 2026-08-20 09:43:04 +02:00
buthed010203 872e967a12 Fix PlacementFragment at large ui scales. (#12515) 2026-08-20 03:42:27 -04:00
Anuken 727dacf9bb Fixed #12512 2026-08-19 21:13:42 +02:00
Anuken d5218ad160 Merge remote-tracking branch 'origin/master' 2026-08-19 18:49:07 +02:00
Anuken 7517d89964 Fixed #12509 2026-08-19 18:48:54 +02:00
Kaleinova f5d06edefc Add armor value access to Block and BuildingComp (#12510) 2026-08-19 12:45:23 -04:00
buthed010203 6ce1a323ab Fix preview generation leaking buildings into world (#12511)
This wasn't ever noticed before but now that world logic can do crazy stuff, it causes a lot of issues.
2026-08-19 12:45:07 -04:00
Anuken 31436ac146 Merge remote-tracking branch 'origin/v9' into v9 2026-08-19 10:40:20 +02:00
Anuken d827f2e218 Cleanup 2026-08-19 10:40:11 +02:00
Anuken 0d8eaa1a1f Merge remote-tracking branch 'origin/master' into v9
# Conflicts:
#	core/src/mindustry/mod/DataImagePacker.java
2026-08-19 10:39:37 +02:00
buthed010203 5184b5e6e1 Fix texture streaming races: (#12505)
- Double sending (large texture followed by small texture with same name, large one could arrive after small one and overwrite it).
- Add then remove (a large texture could be removed before it was done being added).
2026-08-19 04:38:34 -04:00
buthed010203 ce6e4f02e0 Support color in stack. (#12507) 2026-08-19 04:37:31 -04:00
Anuken e130c34a61 Merge remote-tracking branch 'origin/master' 2026-08-19 10:37:20 +02:00
Anuken 71f4ec957f Fixed #12506 2026-08-19 10:37:10 +02:00
西红柿汤 9d6379dbf8 Update getblock description for accuracy (#12485) 2026-08-18 14:55:33 -04:00
Anuken 809cf8baad Fixed #12496 2026-08-18 12:08:02 +02:00
Anuken da911f3877 Fixed #12498 2026-08-18 11:37:58 +02:00
Anuken ff580d8a06 Fixed #12491 2026-08-18 11:12:22 +02:00
Anuken d38ec52faa Fixed #12497 2026-08-18 11:07:55 +02:00
Anuken abebad2f5f Fixed #12495 2026-08-18 11:00:55 +02:00
Github Actions 1befd890cc Automatic class mapping and map name update 2026-08-14 16:24:02 +00:00
Anuken 56485c39f4 Merge fixes 2026-08-14 12:21:58 -04:00
Anuken 292552618a Merge fixes 2026-08-14 12:20:56 -04:00
Anuken e26205a4f7 Merge remote-tracking branch 'origin/master' into v9
# Conflicts:
#	core/assets/bundles/bundle_ca.properties
#	core/assets/scripts/global.js
#	core/src/mindustry/mod/DataImagePacker.java
#	gradle.properties
#	tools/src/mindustry/tools/SchemaGenerator.java
2026-08-14 12:20:03 -04:00
Anuken e8bf80a1d2 Fixed mod icons not displaying when newly imported 2026-08-14 12:12:52 -04:00
Anuken f695ad7e60 Fixed UiTreeBuilder stack ID bug 2026-08-13 21:03:59 -04:00
Anuken 58d1c3265e Merge remote-tracking branch 'origin/master' 2026-08-13 14:55:37 -04:00
Anuken 774b2b64d3 Remote methods for tile fill 2026-08-13 14:55:29 -04:00
Anuken 099971d8f6 RoboVM update 2026-08-13 12:39:55 -04:00
Github Actions 275d357b6c Automatic bundle update 2026-08-13 15:42:47 +00:00
Anuken 11d79aceec Merge remote-tracking branch 'origin/master' 2026-08-13 11:42:02 -04:00
Anuken f6fa8fb326 PR cleanup 2026-08-13 11:41:55 -04:00
Github Actions 6b849a4017 Automatic bundle update 2026-08-13 15:39:23 +00:00
方而静 8ac7087adf core: input: Optimize bridge placement with DP and unify bridge handling (#11908)
* core: input: Optimize bridge placement with DP and unify bridge handling

Refactor `Placement.calculateBridges` to use dynamic programming for
smarter bridge insertion when dragging conveyor lines across obstacles.
Introduce a `BridgePlacer` interface to consolidate logic for
`ItemBridge` and `DirectionBridge`, reducing code duplication and
improving maintainability.

The DP algorithm considers conveyor, junction, and bridge costs to
minimize placement steps while avoiding unnecessary gaps.

Signed-off-by: szdytom <szdytom@qq.com>

* core: add setting option for smarter conveyor bridge placement

Introduce a new "Smarter Bridge Placement (Experimental)" setting that
toggles between the legacy bridge calculation and an optimized DP-based
algorithm. Preserve the original placement logic to maintain stability
while allowing users to test the improved pathfinding behavior.

Add localized strings for the new setting for English and
Simplified Chinese in the respective bundles.

Suggested-by: loleczkowo <loleczkowo@loleczkowo.com>
Signed-off-by: szdytom <szdytom@qq.com>

---------

Signed-off-by: szdytom <szdytom@qq.com>
2026-08-13 11:38:47 -04:00
The4codeblocks 9cb67b15da add+implement LDrawable interface, for modding purposes (#12056)
* add+implement LDrawable interface

* * imports

* cleanup

* tiled
2026-08-13 11:36:52 -04:00
Github Actions 313e80448a Automatic class mapping and map name update 2026-08-13 15:31:57 +00:00
Github Actions be90286451 Automatic bundle update 2026-08-13 15:31:03 +00:00
buthed010203 0f444a8ad7 Implement image streaming API (#12482) 2026-08-13 11:30:23 -04:00
Joan Josep c5d6814c50 Update bundle_ca.properties (#12474)
* Update bundle_ca.properties

* Update bundle_ca.properties
2026-08-13 11:30:16 -04:00
SITUVNgcd 491cd90af8 Update Vietnamese translation (#12469)
* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/6b431ece1b8a9e9fdfb7d4162eae9c7a5471c24c

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/6b431ece1b8a9e9fdfb7d4162eae9c7a5471c24c
2026-08-13 11:30:07 -04:00
wan fb1cde88d8 Update bundle_ja.properties (#12480) 2026-08-13 11:28:32 -04:00
wan a1fe1f7a9e Update bundle_ja.properties (#12470)
* Update bundle_ja.properties

* Update bundle_ja.properties
2026-08-13 11:25:09 -04:00
Anuken d27480312a Fixed #12484 2026-08-13 11:24:15 -04:00
Anuken 43d3aa6460 Fixed layout issues with outdated servers / .d.ts generation script 2026-08-12 14:11:59 -04:00
Anuken a819f80520 Proper interface override support for iOS in Javascript 2026-08-12 01:32:04 -04:00
Anuken 5c7e462e9c Rhino update 3 2026-08-11 21:55:19 -04:00
Anuken 92219de5b7 Rhino update, again 2026-08-11 21:34:20 -04:00
Anuken 02e789687d Updated Rhino 2026-08-11 21:09:07 -04:00
Anuken c5d67a56fd Merge remote-tracking branch 'origin/v9' into v9 2026-08-11 14:31:24 -04:00
Anuken 807e9a4db5 Remove Elem class 2026-08-11 14:31:14 -04:00
Anuken 3f3c0d4911 Moved fancy checkbox to separate class 2026-08-11 14:24:30 -04:00
NiTiSonandAnuken 340b2192b9 Ease access to the additionalSetup field (#12478)
* Fixed #12473

* Fixed #12472

* Fixed #12471

* ItemModule.empty capacity check

* JSON schema generation tweaks / Logic link name fixes

* Ease access to the additionalSetup field

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-11 14:11:50 -04:00
Anuken ab0cc53ae7 Fixed #12477 2026-08-11 14:05:33 -04:00
Anuken e7d214d43b JSON schema generation tweaks / Logic link name fixes 2026-08-10 22:38:45 -04:00
Anuken a5c6b9d240 ItemModule.empty capacity check 2026-08-10 15:58:58 -04:00
Anuken ec02e87d94 Fixed #12471 2026-08-10 15:53:40 -04:00
Anuken 90eb03cf78 Fixed #12472 2026-08-10 14:39:57 -04:00
Anuken 4aa0c64567 Merge remote-tracking branch 'origin/master' 2026-08-10 14:34:53 -04:00
Anuken c800574c4c Fixed #12473 2026-08-10 14:34:44 -04:00
Anuken 9ebf3b966e Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-08-10 12:15:15 -04:00
The4codeblocks 1c4245d070 add+use LPrintable interface, for modding purposes (#12047)
* the beginnings of LPrintable.java

* implement interface
2026-08-09 21:17:02 -04:00
Anuken 59ca250593 Unloader item crash fix 2026-08-09 16:40:31 -04:00
Anuken 269a3f5841 Merge remote-tracking branch 'origin/master' 2026-08-08 14:40:16 -04:00
Anuken 9302dc1f44 Fixed spurious commits 2026-08-08 14:40:09 -04:00
Github Actions 694e722ce8 Automatic class mapping and map name update 2026-08-08 17:46:47 +00:00
Anuken 9fc5b187bf Merge remote-tracking branch 'origin/master' 2026-08-08 13:44:55 -04:00
Anuken beb45688b2 Fixed message block edit misalignment on mobile 2026-08-08 13:44:49 -04:00
Github Actions 9dd19c7559 Automatic class mapping and map name update 2026-08-08 17:27:12 +00:00
Anuken c018a6feb0 Updated minimum iOS version as per Apple's requirements 2026-08-08 13:25:56 -04:00
Github Actions 1d8da1531d Automatic class mapping and map name update 2026-08-08 15:55:48 +00:00
Anuken 38a921558d Fixed 'escelating' bundle typo 2026-08-08 11:54:40 -04:00
Github Actions f0d29df1d8 Automatic bundle update 2026-08-08 15:50:10 +00:00
Ademdu136andAnuken 40951ad576 Update bundle_fr.properties (#12199)
* Update bundle_fr.properties

Added more french titles for zones and re-did some of them.

* Update bundle_fr.properties

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-08 11:49:27 -04:00
Blabla31i be15bdee46 Update bundle_tr.properties (#12084)
Some typo's are fixed and made one translation from "modded" to "modlanmış"
2026-08-08 11:45:46 -04:00
wan d499f67839 Update bundle_ja.properties (#12468) 2026-08-08 11:44:57 -04:00
1ue999and1ue999 53dba45410 i sensed some memory (#12465)
Co-authored-by: 1ue999 <1ue999owo@gmail.com>
2026-08-08 11:41:20 -04:00
Anuken 26e3452f7c Fixed tests 2026-08-08 11:40:55 -04:00
Anuken 52d23725a7 Fixed #12467 2026-08-08 11:31:26 -04:00
Anuken b88591c51b Fixed mirror filter line clip issue after PR 2026-08-07 23:32:29 -04:00
Anuken 49f5e584eb Merge remote-tracking branch 'origin/master' 2026-08-07 23:26:18 -04:00
Anuken 15641b7f2d Minor cleanup & JSON mod folder loading fix 2026-08-07 23:26:09 -04:00
bd75e7bb27 Make mirror axis draggable (#11993)
* Add draggable mirror axis

* Add comments for mirror axis

---------

Co-authored-by: DeterMination-Wind <228482103+DeterMination-Wind@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-07 23:25:51 -04:00
Github Actions 6b431ece1b Automatic bundle update 2026-08-08 03:19:50 +00:00
Pyratite No Lead dbecd74428 Update Simplified Chinese Translation (#12452)
* Update Simplified Chinese Translation

* Fix typo

* Update Simplified Chinese Translation
2026-08-07 23:19:07 -04:00
Sunky.MP3G e58c886d60 Ru translation (#12445)
* Update bundle_ru.properties

* forgor

* wowowowowow mod warning haha turn your device into brick
2026-08-07 23:19:00 -04:00
Zaxerf1234 70f92077b5 Update uk_UA bundle translation (#12438)
* Update contributors

* Update bundle_uk_UA.properties

* Translate new fields
2026-08-07 23:18:52 -04:00
Kevin Vilyan 5c60109a88 Update Bundle ID (#12433)
* Translate New String. Bundle ID

* server.sort

* Update bundle_id_ID.properties

* noticed inconsistency

* minor revision

* translate mod warn
2026-08-07 23:18:42 -04:00
SITUVNgcd 04bb82d622 Update Vietnamese translation (#12431)
* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/96393067bf38070aa56c83a5fa90a0445c4828e8

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/c9fe48f6bb945b26fff315bca917cce5c322882b

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/65e932039bacee625158c322fec41084130eacdb
2026-08-07 23:18:35 -04:00
summoner 0b13529061 Translation: Update bundle_hu.properties (#12425)
* Translation: Update bundle_hu.properties

Translate new string

* Update bundle_hu.properties

Translate new strings

* Translation: Update bundle_hu.properties

Translate new strings
Follow the changes of the english bundle

* Translation: Update bundle_hu.properties

Fix wording

* Translation: update bundle_hu.properties

Translate new strings
2026-08-07 23:18:28 -04:00
VireVeonix 3ffdba4ee1 Update ForceProjector.java (#12463)
let people define forceShrink themselves in order to not have this effect be hardcoded to always display 6 sides
2026-08-07 16:55:43 -04:00
Anuken 257a28e4d7 Button checked for UI builder 2026-08-07 12:43:12 -04:00
Anuken 220b965d3c Button group for UI builder 2026-08-07 10:30:33 -04:00
Anuken 9eea0969cd Closes #11273 2026-08-06 22:05:04 -04:00
Anuken e7c4e44530 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/mod/DataImagePacker.java
#	gradle.properties
2026-08-06 21:54:58 -04:00
Anuken 424b4ba8a7 Misc cleanup & minor fixes 2026-08-06 21:53:08 -04:00
Anuken 5a9603cf48 Do not update units when in editor 2026-08-06 18:08:33 -04:00
Anuken 54105ce586 Fixed #12457 2026-08-06 17:43:36 -04:00
Anuken 96cd2e20fe UI builder stack support 2026-08-06 16:29:03 -04:00
Anuken fb16df23af Fixed MapIO#generatePreview failing or corrupting current world 2026-08-06 14:40:10 -04:00
Anuken c27cd836d8 Docs & UI hot reload line number preview 2026-08-06 14:14:23 -04:00
Cardillan 68bfae2cf3 Finish processor link changes optimization / avoid unwanted 'wait' resets (#12232)
* Finish processor link changes optimization

* Convert links to normal variables and back
2026-08-06 14:11:31 -04:00
JasonP01 491e2d923b fix renaming
todo: ensure it doesnt write the status chance twice
2026-08-06 20:11:30 +02:00
JasonP01 3b658e0fc5 fix the values 2026-08-06 19:51:17 +02:00
JasonP01 9b357dbe8c possible lighting bullet fix 2026-08-06 19:22:51 +02:00
JasonP01 5f77b10bf9 fix status value 2026-08-06 19:20:35 +02:00
Anuken 3d7a930dcd Display lines in UI parser 2026-08-06 12:27:02 -04:00
Anuken d7baddecdd Fixed drawables being cached after data image reload 2026-08-06 11:55:40 -04:00
EggleEgg 2724337aad back, probably 2026-08-06 06:26:47 +02:00
JasonP01 42b02ec944 fix problems 2026-08-06 05:44:04 +02:00
JasonP01 10968885c6 merge origin 2026-08-06 05:33:14 +02:00
JasonP01 cf7dbf1090 ; 2026-08-06 05:32:38 +02:00
Jason 116c2f9300 Merge branch 'Anuken:master' into statusChance 2026-08-06 05:26:44 +02:00
JasonP01 e38d49399b merge upstream 2026-08-06 05:25:38 +02:00
Anuken 1e14d37387 Fixed seeking mp3 files 2026-08-05 23:11:34 -04:00
Anuken 83f8d89bf3 Fixed \n parsing in UI DSL 2026-08-05 23:11:22 -04:00
Anuken d7714654f1 sgdsgsdg 2026-08-05 22:52:12 -04:00
Anuken eae749bbf1 iOS fixes 2 2026-08-05 22:49:19 -04:00
Anuken 20eee370ff iOS task fixes 2026-08-05 22:45:17 -04:00
Anuken cbf3ca6650 arc 2026-08-05 17:23:32 -04:00
Anuken 8718814bff Fixed UI hot reload not updating background 2026-08-05 14:59:37 -04:00
Github Actions fc0113c887 Automatic bundle update 2026-08-05 15:54:40 +00:00
Anuken 82951f6855 More UI DSL fields 2026-08-05 11:53:34 -04:00
Anuken 467f61583b Utility class for DSL UI hot reloading 2026-08-05 03:21:25 -04:00
Anuken 97b9afb85a Fixed #12453 2026-08-04 23:33:37 -04:00
Anuken 16c9fbe148 arc 2026-08-04 21:48:52 -04:00
Anuken 87b1bc1ad6 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/mod/DataImagePacker.java
#	gradle.properties
2026-08-04 21:46:46 -04:00
Anuken 21ea978455 Stricter JSON allow-list 2026-08-04 21:42:53 -04:00
Anuken 170cf7f8c0 UI builder system fixes and cleanup 2026-08-04 16:33:03 -04:00
Anuken 7ebfe8990d Fixed #12449 2026-08-04 14:05:14 -04:00
Anuken 390dfad960 Scheam generator cleanup 2026-08-04 13:44:38 -04:00
Anuken c197382955 Conditional UI building for servers (e.g. portrait/landscape) 2026-08-04 12:37:27 -04:00
Anuken b6a2725c77 Schema cleanup 2026-08-04 02:27:01 -04:00
Anuken 5b8f7d5c93 Schema generator moved to separate class 2026-08-03 23:30:53 -04:00
Anuken 355ea97b50 Schema default 2026-08-03 20:21:01 -04:00
Anuken 0e4883c228 Merge remote-tracking branch 'origin/master' 2026-08-03 17:11:36 -04:00
Anuken 2fd3ae7d88 Scripts updated 2026-08-03 17:11:25 -04:00
Github Actions addf1ddf6d Automatic class mapping and map name update 2026-08-03 20:09:55 +00:00
Anuken 75515288cd Dialog UI builder for servers 2026-08-03 16:07:46 -04:00
Anuken 5daa268748 Cleanup 2026-08-02 04:18:40 -04:00
Anuken ff427fbffb Fixed pack logging 2026-08-02 02:38:09 -04:00
Anuken 81d2043d06 Floor edge crash fix 2026-08-02 02:27:02 -04:00
Anuken 9809cb149a Merge remote-tracking branch 'origin/master' 2026-08-02 02:16:06 -04:00
Anuken 1fdb6ce3db Fixed #12443 2026-08-02 02:16:00 -04:00
Github Actions 65e932039b Automatic bundle update 2026-08-02 06:13:28 +00:00
SITUVNgcd a2ac8bf0d2 Correct description to large shield projector block (#12444) 2026-08-02 02:12:40 -04:00
Anuken ea8cad4f2a Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-08-02 01:14:26 -04:00
Anuken 4a89218e69 Merge remote-tracking branch 'origin/v9' into v9 2026-08-02 01:14:11 -04:00
Anuken 8109637349 Fixed server json usage 2026-08-02 00:24:53 -04:00
Anuken 9ae1ccebf1 Fixed server json usage 2026-08-02 00:22:23 -04:00
Anuken b41f40e6ff Removed writer field from Json 2026-08-01 23:55:28 -04:00
Anuken 43025b373a cleanup 2026-08-01 23:37:19 -04:00
Anuken 8fad301da8 Jval migration made functional 2026-08-01 22:53:46 -04:00
Anuken cf1b2e38c2 Merge remote-tracking branch 'origin/master' 2026-08-01 18:39:50 -04:00
Anuken f9ab9e6f96 Fixed maxPhysicsTime reset 2026-08-01 18:39:44 -04:00
Github Actions c9fe48f6bb Automatic bundle update 2026-08-01 21:53:53 +00:00
EggleEgg 574506507f Mixtech thor reactor balancing (#11600)
* mixtech thor reactor heat balancing

* consume thor like crazyyy

* per side

* only produce heat when working instead, since increasing or reducing ambient cooldown doesnt do much

* dont break ratios thanks

* pontentially

* potentially god fucking dammit

* slower and safer reactor

* slower and safer reactor

* do not

* db entry stuff
2026-08-01 17:53:03 -04:00
Anuken d91028a376 Merge remote-tracking branch 'origin/master' 2026-08-01 17:43:31 -04:00
Anuken b7148edba5 Minor doc fixes 2026-08-01 17:43:24 -04:00
Github Actions b2876d5916 Automatic bundle update 2026-08-01 21:18:46 +00:00
Jonathan "Not quite" TempoandAnuken ad2bae37f1 Update bundle_it.properties (#12177)
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-01 17:18:09 -04:00
Vladislav SuchkovandAnuken 5330e8d45d Translation: Update bundle (en) & bundle_ru (#11777)
* update bundle, bundle_ru

* typo

* more tweaks

* forgor a line break

* remove usage of a var (removed in #1bdac35)

* Apply suggestions from code review

Co-authored-by: Anuken <arnukren@gmail.com>

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-01 16:27:33 -04:00
Github Actions 3f59a53024 Automatic bundle update 2026-08-01 20:24:51 +00:00
6e5b3e519b Update bundle.properties (#11911)
* Update bundle.properties

added descriptions to editor only blocks

* Update bundle.properties

best i could try

* '⚠' != '⚠️'

* Apply suggestion from @Anuken

---------

Co-authored-by: 50275 <68676339+50275@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-01 16:24:04 -04:00
Github Actions e962ed5a25 Automatic bundle update 2026-08-01 19:59:59 +00:00
The4codeblocksandAnuken caa6801ec4 Not privileged setrate [POSTREFORMAT] (#10520)
* npsr

* npsr deconflict

* npsr cat

* anuke is not a modder

* Update LExecutor.java

* Update LogicBlock.java

* remove nopriv reset

* fix

* avoid credit duplication

* fix version conflict

* Apply suggestion from @Anuken

* Apply suggestion from @Anuken

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-01 15:59:22 -04:00
Anuken 6c7bf7511a Separate perf counters for unit physics and waiting for physics completion 2026-08-01 14:03:51 -04:00
Anuken 6f3e4d7f25 Minor HUD hide fix 2026-08-01 02:32:28 -04:00
Redstonneur1256andAnuken 2ca5d373d5 Logic cutscene improvements (#10861)
* Logic cutscene improvements

* Add `cutscene shake`

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-08-01 02:31:31 -04:00
Anuken fb3fff9894 Fixed tests 2026-08-01 02:31:22 -04:00
Anuken e5e417265d Do not force LogicAI for unbind/within 2026-08-01 01:11:37 -04:00
Anuken 94453c127c Merge remote-tracking branch 'origin/master' 2026-08-01 01:02:33 -04:00
Anuken 0408389fda arc 2026-08-01 01:02:31 -04:00
Anuken 6ab65f735d Workaround for TimeControl-specific NaN bug 2026-08-01 01:02:15 -04:00
Anuken 296d6cbdb9 misc fixes 2026-08-01 00:36:51 -04:00
Anuken 474f486980 Physics refactor 2026-08-01 00:18:15 -04:00
Anuken 3af897de1d Physics refactor 2026-07-31 23:58:40 -04:00
Jason 2a72d5e3bf fix NaN (#12436) 2026-07-31 22:32:26 -04:00
Anuken cb6c5b1c5d This may have been a bad idea 2026-07-30 22:30:45 -04:00
Github Actions 33b7f32eb5 Automatic bundle update 2026-07-31 02:02:44 +00:00
Anuken 02785f49e8 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/assets/bundles/bundle_pt_BR.properties
#	gradle.properties
2026-07-30 21:56:03 -04:00
Anuken 20da6a38ab Fixed tests 2026-07-30 19:02:04 -04:00
Anuken 0e2f071d63 Fixed #12430 2026-07-30 16:31:42 -04:00
Anuken 37194ce6ab Merge remote-tracking branch 'origin/master' 2026-07-30 15:47:04 -04:00
Anuken fa2b202dcf MinAPI Android cleanup 2026-07-30 15:46:51 -04:00
Kaleinova d07016eea9 Translation: Update zh_CN translation (#12399)
* Translation: Update zh_CN translation

* Translation: Update zh_CN translation

Updated the synchronization description.
2026-07-29 17:40:47 -04:00
BalaM314 71c15e996f Fix push direction of offset arc shields (#12429) 2026-07-29 17:40:33 -04:00
Anuken e56227b2b0 Fixed #12428 2026-07-29 17:40:15 -04:00
Yura Bobalo 6f2af6013c Fix translation for advanced launch pad description (#12426)
Fixed a typo in the Ukrainian translation for the advanced launch pad description.
2026-07-27 15:28:16 -04:00
BalaM314 384c8d576b Fix rotation of hover parts (#12424) 2026-07-27 12:19:48 -04:00
Github Actions 96393067bf Automatic bundle update 2026-07-27 16:08:25 +00:00
Anuken 8ce8423758 Merge remote-tracking branch 'origin/master' 2026-07-27 12:07:27 -04:00
Anuken d3a50f6951 Added button to sort servers by player count 2026-07-27 12:07:21 -04:00
Github Actions 048ea6e56f Automatic bundle update 2026-07-26 16:13:15 +00:00
Anuken 4e85807aa9 Fixed #12421 2026-07-26 12:12:28 -04:00
Anuken c407e38516 Merge remote-tracking branch 'origin/master' 2026-07-25 22:09:15 -04:00
Anuken 8a1b3c291c Fixed #12419 2026-07-25 22:09:06 -04:00
Jhonnata André ef294666ae Add jhonnata.andre to contributors list (#12412)
Commit b0f5740
Finalizes pending translations and synchronizes the pt_BR bundle with the latest bundle.properties (English). (#12283)
2026-07-24 21:26:59 -04:00
Cardillan d2c35d7b4b Fixes tileable displays not working with marker texture after map load (#12415) 2026-07-24 21:26:43 -04:00
EggleEgg 330ddc1c23 Revert "Fix fortress and collaris bullets dying before reaching their intende…" (#12414)
This reverts commit 3434c35334.
2026-07-24 21:26:27 -04:00
Kirill 3434c35334 Fix fortress and collaris bullets dying before reaching their intended position (#12408)
* Fix fortress/collaris bullets dying before reaching intended range

* Lower maxRange/rangeOverride to match actual bullet travel distance
2026-07-24 13:31:49 -04:00
ThePullerCell bae93299c7 Demixeled large shield projector (#12413)
* Rename large-shield-projector.png to large-shield-projector-to-delete.png

* Add files via upload

* Rename large-shield-projector-improved.png to large-shield-projector.png

Demixeled large shield projector

* forgot to upload team sprite

* Delete core/assets-raw/sprites/blocks/defense/large-shield-projector-to-delete.png

ISTG DID I NOT DELETE THE DAMN TO DELETE SPRITE
2026-07-24 13:31:07 -04:00
Anuken 62b8bdd7e3 Fixed #12410 2026-07-24 13:30:29 -04:00
Anuken 729a4f50ba Fixed #12409 2026-07-24 13:17:28 -04:00
Anuken 9af6cc0c6a Merge remote-tracking branch 'origin/master' 2026-07-23 23:20:11 -04:00
Anuken b91800d821 Closes #11356 2026-07-23 23:20:02 -04:00
EggleEgg 5cbdd3ef0c possible patch 1: least risk (#12008) 2026-07-23 23:15:33 -04:00
Github Actions de1584ece7 Automatic bundle update 2026-07-24 03:04:48 +00:00
Anuken 21b98b809f Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-07-23 23:04:00 -04:00
Anuken 2235e35939 arc 2026-07-23 23:03:57 -04:00
Jhonnata André b0f574071a Finaliza traduções pendentes e sincroniza o bundle pt_BR com o bundle.properties (inglês) mais recente. (#12283)
Translated various English strings to Portuguese in the properties file, enhancing localization for Portuguese-speaking users.

Alterações

Traduzido conteúdo que ainda estava em inglês (~67 chaves), incluindo:

Textos de UI (área de transferência, pausa, importação de mods, tela de erro de mod)
Descrições de setores de campanha (Ravine, Facility 32M, Tainted Woods, Sunken Pier, Atolls, Frontier, Infested Canyons, Testing Grounds, Perilous Harbor, Weathered Channels, Mycelial Bastion, Littoral Shipyard)
Descrições de habilidades e balas
Seção técnica de lógica (lglobal.*, lst.*, graphicstype.print) usada pelos processadores de mundo

Adicionadas 90 chaves que estavam ausentes (não existiam no bundle pt_BR), sincronizando com o bundle.properties atual — principalmente o novo sistema de Data Patches & Assets (asset.*, patch.*, content.*), além de export.file, import.file, copy.clipboard, workshop.browse, edit.menu, settings.dev, rules.hidespawns, lst.playmusic, entre outras.
Nenhuma chave existente foi removida. Chaves que não existem mais no bundle em inglês (ex: schematic.copy, editor.patches.*, waves.edit) foram mantidas por compatibilidade.

Terminologia usada
Consistente com o restante do arquivo: horda = wave, núcleo = core, torreta = turret, unidade = unit, bloco = block, ativo = asset, Patches mantido em inglês (já usado no arquivo original).
2026-07-23 23:03:44 -04:00
1ue999and1ue999 0fb3c6183e implement https://github.com/Anuken/Mindustry-Suggestions/issues/6426 (#12373)
* implement something

* turns out we had no vars for status effects

* seconds, not frames

* @status-name, setprop status

* lossyless?

* secondary commit

* status changes

* ui uiing

---------

Co-authored-by: 1ue999 <1ue999owo@gmail.com>
2026-07-23 23:00:25 -04:00
SITUVNgcd 7f484c34a4 Update Vietnamese translation (#12394)
* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/a39660ec88961476c110e9e6073ef6b041beea9b

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/a39660ec88961476c110e9e6073ef6b041beea9b
2026-07-23 22:58:48 -04:00
Anuken efb218653b Logic field layout autowrap 2026-07-23 15:52:44 -04:00
Anuken a7f53421e3 Merge remote-tracking branch 'origin/master' 2026-07-22 15:37:57 -04:00
Anuken 55908f9112 Public flow rate measurement parameters 2026-07-22 15:37:47 -04:00
Anuken a7053b9c1c Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-07-22 10:03:28 -04:00
Sunky.MP3G 8a183e72d4 Ru translations (#12400)
* Music logic, block limit

* Better "workshop" translation and some untranslated lines

* Why did I only do this now
2026-07-21 19:10:52 -04:00
Anuken 8b672526e5 Fixed tab selection 2026-07-21 19:09:25 -04:00
Anuken 4d39837cf3 Merge branch 'sound-selector-tabs' of https://github.com/Abdullah-Ajeebi/Mindustry into Abdullah-Ajeebi-sound-selector-tabs 2026-07-21 18:34:10 -04:00
Anuken ae274d35c7 Fixed #12397 2026-07-21 18:31:17 -04:00
Abdullah 2fd3ab74a0 Actually use play(..., AudioBus) because IDEA is trying to be funny and whatnot (it somehow never updated Arc) 2026-07-21 10:52:53 +03:00
Anuken 62dbbe39d1 Patches below stack trace 2026-07-20 17:42:38 -04:00
Anuken 6425f37e68 arc 2026-07-20 15:41:26 -04:00
Anuken d120f1d730 Merge remote-tracking branch 'origin/master' 2026-07-20 15:41:18 -04:00
Anuken 21290057f0 Fixed #12392 2026-07-20 15:41:08 -04:00
Anuken 5558211c4f Fixed #12392 2026-07-20 15:40:43 -04:00
WMF feab7aa908 datapatch planet requirement fix (#12389) 2026-07-20 15:30:48 -04:00
Cardillan 7e416f4251 Set result to null when sensor fails (#12391) 2026-07-20 15:30:13 -04:00
BalaM314 d23f072922 Unbork bug report template description (#12393)
the text has been totally wrong for years and i never noticed
2026-07-20 15:29:49 -04:00
Anuken 3ecdd5ff2a Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-07-19 17:46:06 -04:00
Github Actions c9686eb5d0 Automatic bundle update 2026-07-19 21:31:33 +00:00
西红柿汤 509cafe386 Add files via upload (#12379) 2026-07-19 17:30:48 -04:00
summoner 58642efa83 Translation: Update bundle_hu.properties (#12367)
* Translation: Update bundle_hu.properties

Fix string

* Translation: Update bundle_hu.properties

translate new string

* Translation: Update bundle_hu.properties

Translate new string
2026-07-19 17:30:40 -04:00
adex345 4bddbfa9ca Changed incorrect "Prąt" to "Prąd" in Polish translation. (#12385) 2026-07-19 17:28:24 -04:00
AbdullahandCopilot 8713c41741 Make sounds actually play first try, stop sounds on dialog close, and add playback indicator.
Use temporary UI bus for preview playback, retry start on next frame and after short delay, stop preview when dialog closes, update UI icon to indicate playback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-18 05:42:06 +03:00
Anuken 1ada6b9fdd Fixed startup dialog on mobile 2026-07-17 16:17:45 -04:00
Anuken 6209a63bba Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/type/SectorPreset.java
#	core/src/mindustry/type/StatusEffect.java
2026-07-17 15:54:22 -04:00
Github Actions a39660ec88 Automatic bundle update 2026-07-17 16:18:36 +00:00
Anuken 81655bbc99 Block placement limits rule for servers 2026-07-17 12:17:28 -04:00
Anuken 5779583a65 Replacement when outlining certain content 2026-07-16 18:46:11 -04:00
Anuken db14d9f086 Rules margin fix 2026-07-16 18:37:51 -04:00
Anuken 366e54784a Fixed sector icon generation 2026-07-16 00:05:42 -04:00
Anuken fc8d70b12f Cleanup 2026-07-15 16:41:29 -04:00
Anuken 7af49d733d Merge branch 'master' into v9
# Conflicts:
#	gradle.properties
2026-07-15 16:38:10 -04:00
Anuken fb34738d60 Cleanup 2026-07-15 16:37:35 -04:00
Anuken 2e74261566 Removed redundant URL handling in iOS 2026-07-15 16:21:32 -04:00
Anuken 09a45ee2fb Fixed mysterious missing conveyors in schematics / Better schematics import handling 2026-07-15 15:44:37 -04:00
Anuken aa7c39636c Merge remote-tracking branch 'origin/master' 2026-07-15 15:30:03 -04:00
Anuken 786194b0b9 Fixed #12370 2026-07-15 15:29:57 -04:00
Github Actions 23fb20abe3 Automatic bundle update 2026-07-15 18:42:10 +00:00
Anuken 5e426a60c1 Support for mindustry:// URLs for joining servers on Android 2026-07-15 14:41:28 -04:00
Anuken 91c3e50771 Android file chooser fixes & support for save loading from file browser 2026-07-15 14:21:38 -04:00
Anuken cef447356b Cleanup 2 2026-07-15 12:07:18 -04:00
Anuken 965550ab0d Antialiasing cleanup 2026-07-15 12:04:34 -04:00
Anuken 8761f0f810 Merge cleanup 2026-07-15 11:52:56 -04:00
Anuken 3d2521a06c Merge remote-tracking branch 'origin/v9' into v9 2026-07-15 11:49:18 -04:00
Anuken 1924e1fb0e Merge cleanup 2026-07-15 11:49:12 -04:00
Anuken 98afd42aac Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/ctype/UnlockableContent.java
#	gradle.properties
2026-07-15 11:47:48 -04:00
Anuken 4133f3fa48 Sector icon outlines (untested) 2026-07-15 11:47:04 -04:00
Anuken 75e0f20964 Somehow this fixed unloader centering 2026-07-15 08:52:53 -04:00
Anuken c0dd4d09f9 Merge remote-tracking branch 'origin/master' 2026-07-15 08:42:23 -04:00
Anuken d5b8726c8c Data editor UI layout fixes 2026-07-15 08:42:17 -04:00
Github Actions 6c09e9f09a Automatic bundle update 2026-07-15 02:45:32 +00:00
Anuken fbf4482c73 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/assets/bundles/bundle_bg.properties
#	core/src/mindustry/world/Block.java
#	gradle.properties
2026-07-14 22:44:23 -04:00
Github Actions 167be4e4a5 Automatic bundle update 2026-07-15 02:29:35 +00:00
summoner 21bc2a108b Translation: Update bundle_hu.properties (#12356)
Translate new strings
Follow the changes of the english bundle
2026-07-14 22:28:51 -04:00
motorhce 3820baa885 Update bundle_bg.properties (#12361)
I have read and retranslated the untranslated lines. Also fixed some mistakes.
2026-07-14 22:28:44 -04:00
Github Actions 665e458409 Automatic class mapping and map name update 2026-07-15 02:26:53 +00:00
Anuken 39a056e09f Fixed maps (again?) 2026-07-14 22:25:50 -04:00
Anuken 823a61670a Map fixes 2026-07-14 22:20:59 -04:00
Anuken 8a60e96f0e Don't generate misleading blank block icons 2026-07-14 22:16:42 -04:00
Anuken 1ee1d4398a Merge remote-tracking branch 'origin/master' 2026-07-14 22:05:48 -04:00
Anuken 3aff70b948 Fixed #12365 2026-07-14 22:05:43 -04:00
Github Actions bf3316b110 Automatic class mapping and map name update 2026-07-15 01:57:52 +00:00
Anuken f26fe0e821 Fixed #12363 2026-07-14 21:56:20 -04:00
Anuken 4e3e232a30 Fixed wrong rule write for music 2026-07-14 11:36:14 -04:00
Anuken e60474c7d0 Let SoundControl#findMusic load modded assets 2026-07-14 11:25:05 -04:00
Anuken 08dbcde924 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/assets/bundles/bundle_uk_UA.properties
#	gradle.properties
2026-07-13 13:41:15 -04:00
Anuken 993737a5c5 Temporary workaround for 263 being broken 2026-07-13 13:30:45 -04:00
Anuken 56efff6a0a Removed leftover debug logging 2026-07-13 13:24:25 -04:00
Anuken 3580c2b63d Allow console in editor (desktop) 2026-07-13 12:42:59 -04:00
Anuken e93430019c Submission updates 2026-07-13 12:22:17 -04:00
Anuken dab3f8ef16 Fixed #12355 2026-07-13 12:04:42 -04:00
Anuken 53d602c294 Fixed audio bus assignment issues 2026-07-13 11:54:32 -04:00
Anuken abf52f737a Merge remote-tracking branch 'origin/master' 2026-07-13 11:39:25 -04:00
Anuken 6d51b2e0a0 Fixed 263 not having attack mode 2026-07-13 11:39:18 -04:00
Github Actions 3a527c1292 Automatic bundle update 2026-07-13 15:16:13 +00:00
Kevin Vilyan e1fde4fcfd Translate New Music Rules (#12353) 2026-07-13 11:15:27 -04:00
Anuken 282f21e903 Music volume rule & current playing music var 2026-07-13 11:15:11 -04:00
Anuken 0e87cdafd5 Merge remote-tracking branch 'origin/master' 2026-07-13 10:54:16 -04:00
Anuken 3b29a4877f Fixed #12354 2026-07-13 10:54:09 -04:00
KienNgoo aef729eef6 Fixing minor text issue in bundle_vi.properties (#12342)
Currently, the string for Casual difficulty has rendering issues in Vietnamese - the actual text in-game doesn't match to what's seen in bundle_vi.properties because of shifted diacritics.
My retype fixes that (extremely) minor issue that could annoy a small group of people.
2026-07-13 09:06:03 -04:00
summoner c10cdbe1fc Translation: Update bundle_hu.properties (#12337)
* Translation: Update bundle_hu.properties

Translate new strings
Follow te changes of the english bundle

* Translation: Update bundle_hu.properties

Translate new string

* Translation: Update bundle_hu.properties

Translate new string
2026-07-13 09:05:15 -04:00
sergij098123 c5853eade6 Updated Ukrainian localization (#12343) 2026-07-13 09:05:04 -04:00
SITUVNgcd f90829457a Update Vietnamese translation (#12344)
* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/fcfc42e057bdea64d523e49ab15ad5d8eef03f0f

* Font display issue due to Decomposed Unicode
2026-07-13 09:04:57 -04:00
Sunky.MP3G 4a825a31ae Ru translations (#12330)
* Small fix

* Yet another bunch of translations

* Tweaked Onset text and temoved unnecessary part of payload conv. desc

* Same for ru
2026-07-13 09:04:50 -04:00
Pyratite No Lead 207cfba2bd Update Simplified Chinese Translation (#12346)
* Update Simplified Chinese Translation

* Fix typo
2026-07-13 09:04:31 -04:00
Anuken 2c066e9c8c Merge remote-tracking branch 'origin/master' 2026-07-13 09:04:07 -04:00
Anuken 9cf425164e Made map fixer automatically hide objectives and remove unlocalized prints 2026-07-13 09:04:00 -04:00
Alessandro Suha 56defd8e02 heat: disabled HeatConductors no longer redirect heat (#12352) 2026-07-13 08:50:47 -04:00
Alone c124414aba Fix issue where afterReadAll in Building is never called (#12351)
* "Add a multiPacker parameter to AtlasPackEvent, allowing listeners to add custom textures through the multiPacker parameter."

* introduces a new hook method packSprites(MultiPacker packer) to the Mod class.

* formatting Mods.java

* formatting Mods.java

* formatting Mods.java

* formatting Mods.java

* d

* Update Vars.java

* Refactor mod icon loading for Steam Workshop

* Refactor mod icon loading for Steam Workshop

* Fix issue where afterReadAll in Building is never called

* Fix issue where afterReadAll in Building is never called
2026-07-13 08:30:26 -04:00
Efsfse2280 cc86657f62 Titanium Conveyor-related transport blocks displaySpeed polishing (#12350)
* numbers

* less code

* bruh
2026-07-13 08:29:19 -04:00
Anuken 28d1b99444 Fixed #12347 2026-07-13 08:26:52 -04:00
Anuken d4305f0287 Fixed #12345 2026-07-13 08:25:16 -04:00
Anuken 7241bdece6 Import fixes for v9 2026-07-12 11:45:03 -04:00
Anuken dc5e877af6 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-07-12 11:42:50 -04:00
Anuken 0b3300397b JS import tweaks 2026-07-12 11:41:56 -04:00
Anuken 668c8dfd93 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-07-12 09:25:19 -04:00
Anuken 6e4903f8c6 Fixed Steam stats not fetching 2026-07-12 09:20:29 -04:00
Anuken 0d92ef53ec Merge remote-tracking branch 'origin/master' 2026-07-11 23:00:40 -04:00
Anuken 8a1775ab3f Removed autoFindTarget assignment (not shooting while moving) now that 'hold fire' exists 2026-07-11 23:00:34 -04:00
SomeonesShadeandAnuken 907b4edbf0 A functional not so buggy reload fix (#12336)
* Added handleReload

* Update core/src/mindustry/world/blocks/defense/turrets/Turret.java

Co-authored-by: Anuken <arnukren@gmail.com>

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-07-11 11:50:06 -04:00
Anuken 7ac0ce5bf5 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	core/src/mindustry/graphics/BlockRenderer.java
#	desktop/src/mindustry/desktop/DesktopLauncher.java
#	gradle.properties
2026-07-11 09:29:44 -04:00
Anuken 58118440b9 Fixed music fade issue 2026-07-11 09:11:56 -04:00
Anuken ebfaf13bed Merge branch 'steam-networking-sockets' of https://github.com/Anuken/Mindustry 2026-07-11 08:46:37 -04:00
Anuken 1de3e80525 Fixed sector 20 objectives 2026-07-10 22:29:24 -04:00
Anuken 664e3b96f8 Fixed tests 2026-07-10 22:28:57 -04:00
Github Actions fcfc42e057 Automatic bundle update 2026-07-11 02:21:47 +00:00
Anuken 4a41b50065 Fixed some connection issues 2026-07-10 22:20:52 -04:00
Anuken d1baaad955 Merge branch 'master' of https://github.com/Anuken/Mindustry into steam-networking-sockets
# Conflicts:
#	gradle.properties
2026-07-10 21:59:34 -04:00
Anuken 3cd72e9e34 Submission updates 2026-07-10 21:58:42 -04:00
Anuken c39e2384ec Fixed #12333 2026-07-10 21:51:41 -04:00
Anuken 57309b63a9 Fixed #12332 2026-07-10 21:48:25 -04:00
Anuken ff1bcdef35 Fixed #12334 2026-07-10 21:40:51 -04:00
Anuken 1a3605761c Cleanup 2026-07-10 21:39:46 -04:00
Anuken b195a4a8e5 Cleanup 2026-07-10 19:17:16 -04:00
Anuken 6f11fd4269 Fixed large world sending 2026-07-10 14:00:20 -04:00
Anuken 48556228df Updated steamworks hash 2026-07-10 10:29:00 -04:00
Anuken 81d1554166 Updated steamworks version hash 2026-07-09 21:25:28 -04:00
Anuken 58c942116b Steam networking sockets implementation 2026-07-09 21:20:48 -04:00
Anuken 439799ce8f Merge remote-tracking branch 'origin/master' 2026-07-09 16:50:02 -04:00
Anuken b5b6b55f51 Added natives to dependency jar 2026-07-09 16:49:56 -04:00
Github Actions b48cd24118 Automatic bundle update 2026-07-09 20:47:25 +00:00
Anuken 05aa271ba0 Added music playback rules to UI 2026-07-09 16:46:18 -04:00
Anuken 069f495746 Fixed logic music playback bug 2026-07-09 16:12:10 -04:00
Anuken 9b0b96e1cc Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-07-09 15:34:46 -04:00
Anuken 0ba4359e55 arc 2026-07-09 15:34:43 -04:00
Github Actions 65705cf86e Automatic bundle update 2026-07-09 19:27:43 +00:00
Anuken 38fd53b544 Mod update checker + 'update all' button + SpawnUnit effect parameter 2026-07-09 15:26:26 -04:00
Anuken 5e47aa3bb2 Moved mod browser into separate class 2026-07-09 12:58:48 -04:00
Anuken f194df5f80 Fixed #12321 2026-07-09 12:55:10 -04:00
Anuken 25a5263c21 Fixed #12325 2026-07-09 12:44:23 -04:00
Anuken 86e63beb14 Fixed #12320 2026-07-09 12:38:16 -04:00
Anuken d329a7bed9 Fixed #12319 2026-07-09 12:37:18 -04:00
Anuken 613d5b44e2 Merge remote-tracking branch 'origin/master' 2026-07-09 12:28:31 -04:00
Anuken 179a74ce49 Increased block sprite cache cap 2026-07-09 12:28:25 -04:00
guiY f9f9369082 Update CommandAI.java (#12328) 2026-07-09 12:17:35 -04:00
Anuken 4c2d9d791d Fixed #12324 2026-07-09 12:17:01 -04:00
Anuken 335306f478 Fixed generated regions having a dp- prefix 2026-07-09 11:59:45 -04:00
Anuken b8984db2f7 Fixed incorrect revealed blocks on some maps 2026-07-09 09:01:06 -04:00
Anuken 856a2c5967 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-07-08 23:08:02 -04:00
Anuken 856332c93f Green and blue team palette for blocks is back 2026-07-08 23:07:20 -04:00
Anuken 90464c55cf Caching for mod icons in browser 2026-07-08 22:37:13 -04:00
Anuken be890fcf56 Removed deprecated methods 2026-07-08 10:20:43 -04:00
Anuken a19fa7f871 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-07-08 10:11:26 -04:00
Anuken 114db448dd Minor naval path cost fix 2026-07-08 09:38:10 -04:00
Anuken 6398fa4e1b Fixed #12313 2026-07-08 09:35:18 -04:00
Anuken e34d3d29e7 arc 2026-07-07 21:21:27 -04:00
Anuken 11e88fe009 Fixed #12310 2026-07-07 18:02:28 -04:00
Anuken 36ca01a1a3 Fixed #12311 2026-07-07 17:59:29 -04:00
Abdullah ad4cd7c54a Use asset names in sound selector 2026-07-07 22:19:45 +03:00
Abdullah 93260d4662 Improve sound selector UI 2026-07-07 22:06:28 +03:00
Anuken fc2f39f44c Fixed data patch content displaying as a mod 2026-07-07 14:13:01 -04:00
Anuken a018d53496 Fixed assets jar not including sprites 2026-07-07 14:02:00 -04:00
Anuken 9cadceb7b7 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9
# Conflicts:
#	gradle.properties
2026-07-07 12:59:57 -04:00
Anuken 1ddc69bb60 Fixed incorrect block config offset 2026-07-07 10:13:37 -04:00
Anuken 544f63e101 Fixed incorrect inventory offset 2026-07-07 10:00:06 -04:00
Anuken 92fe219e78 Fixed #12304 / Fixed #12307 2026-07-07 09:35:34 -04:00
Anuken 6d9601b579 Bundle fix 2026-07-07 09:23:49 -04:00
Anuken 567434fe99 arc 2026-07-07 09:16:10 -04:00
Anuken 094726e916 Label ID fix 2026-07-07 09:11:47 -04:00
Anuken e0996e29f4 Fixed #12306 / Fixed #12305 2026-07-07 09:00:38 -04:00
Anuken e25b728089 Fixed #12302 / Fixed #12303 / Fixed #12299 2026-07-07 08:48:43 -04:00
Anuken 5d23c9b3af Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-07-06 20:10:35 -04:00
Anuken 8051a5c8d4 Merge remote-tracking branch 'origin/master' 2026-07-06 18:32:34 -04:00
Anuken 8b3d9504c9 Fixed NoiseEffect clipping 2026-07-06 18:32:28 -04:00
Github Actions f8e804d3cb Automatic bundle update 2026-07-06 21:51:02 +00:00
Denzy 0c96b3f7ed Update Belarusian translation (#12133)
* Update bundle_be.properties

minor changes

* Update bundle_be.properties

* Update bundle_be.properties

* Update bundle_be.properties

* Update bundle_be.properties

* Update bundle_be.properties
2026-07-06 17:50:25 -04:00
Anuken 7af809496e Merge remote-tracking branch 'origin/master' 2026-07-06 17:41:37 -04:00
Anuken b9331331a7 Don't cap reloadCounter in turrets 2026-07-06 17:41:30 -04:00
Cardillan 5e78db1a11 Allow reading links from a processor (#11838)
* Allow reading links from a processor

* Add support for numerical indexes
2026-07-06 17:21:07 -04:00
summoner 72f947634e Translation: Update bundle_hu.properties (#12297)
* Translation: Update bundle_hu.properties

Translate new string

* Translation: Ubdate bundle_hu.properties

Follow the changes of the english bundle
2026-07-06 16:55:44 -04:00
Anuken ed33b04bfc Possible schematics search reset fix 2026-07-06 15:41:40 -04:00
Anuken 9e648dd34f Option for disabling ANGLE on windows 2026-07-06 11:57:44 -04:00
Anuken 1dfdc28c66 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-07-06 00:20:10 -04:00
Anuken 44dee9b285 Removed zoom value rounding 2026-07-06 00:19:48 -04:00
Anuken 80b18bf793 Repack sprites when switching v9/v8 branches 2026-07-06 00:02:45 -04:00
Anuken f00e7c4d85 Fixed lights not rendering 2026-07-05 23:49:02 -04:00
Anuken 308d38bd65 Merge remote-tracking branch 'origin/v9' into v9 2026-07-05 14:17:39 -04:00
Anuken be7f811761 Merge branch 'master' of https://github.com/Anuken/Mindustry into v9 2026-07-05 14:17:27 -04:00
Anuken 0b3ba6f94a More CI updates 2026-07-05 14:16:26 -04:00
Anuken cb3ee2112f More CI updates 2026-07-05 14:15:46 -04:00
Anuken 4d72af7d30 Removed jitpack repo updating, updated CI scripts 2026-07-05 14:13:40 -04:00
Anuken 9704bf37cc Removed jitpack repo updating, updated CI scripts 2026-07-05 14:12:48 -04:00
Github Actions 8d5e02dfbe Automatic class mapping and map name update 2026-07-05 18:06:58 +00:00
Anuken 8318b5cb71 Fetch correct arc branch 2026-07-05 14:04:26 -04:00
Anuken 014f23c7a0 v9 setup (no, there is no new content) 2026-07-05 14:01:04 -04:00
Anuken 910a4e7b00 Merge branch 'array-textures' of https://github.com/Anuken/Mindustry into array-textures-sdl3 2026-07-05 13:43:18 -04:00
Github Actions aef8998058 Automatic bundle update 2026-07-05 17:36:58 +00:00
Anuken 4ae6053ace Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	core/assets/bundles/bundle_hu.properties
#	core/assets/bundles/bundle_ru.properties
#	core/assets/bundles/bundle_th.properties
#	core/assets/bundles/bundle_vi.properties
#	core/assets/bundles/bundle_zh_CN.properties
#	core/assets/bundles/bundle_zh_TW.properties
#	core/src/mindustry/mod/Mods.java
#	gradle.properties
2026-07-05 13:35:11 -04:00
Anuken 112ec4bdff Merge remote-tracking branch 'origin/master' 2026-07-05 13:25:21 -04:00
Github Actions 85aa1f5e34 Automatic class mapping and map name update 2026-07-05 17:25:16 +00:00
Anuken 4e92cd8b5c what? 2026-07-05 13:25:15 -04:00
Kevin Vilyan 717aa69293 Translate asset.exists.audio (#12295) 2026-07-05 13:22:49 -04:00
Anuken 97fce0735d Merge remote-tracking branch 'origin/master' 2026-07-05 13:22:29 -04:00
Anuken 8b64aebe27 Script for updating map names 2026-07-05 13:22:23 -04:00
Github Actions a9258f99d4 Automatic bundle update 2026-07-05 17:05:58 +00:00
Anuken 2fb28e589a Bundle cleanup 2026-07-05 13:04:34 -04:00
Anuken dddce86ec7 Fixed #12296 2026-07-05 12:04:51 -04:00
Anuken a64aae1d78 Updated sector submissions, fixed crash 2026-07-05 12:00:04 -04:00
Anuken 028f1036fb Merge remote-tracking branch 'origin/master' 2026-07-05 11:17:18 -04:00
Anuken 0c2e006cc8 Audio bugfixes & data patch logic sound play support 2026-07-05 11:17:12 -04:00
Github Actions f42b519f20 Automatic bundle update 2026-07-05 14:47:20 +00:00
JniTrRnyandAnuken 41c6f389c7 Update bundle_th.properties (#12289)
Co-authored-by: Anuken <arnukren@gmail.com>
2026-07-05 10:46:03 -04:00
Sunky.MP3G db02b63be6 Fixed ru translations (#12292)
* Fixed ru translations

* Fixed old typo
2026-07-05 10:45:41 -04:00
Github Actions 4805c77eac Automatic bundle update 2026-07-05 14:45:10 +00:00
Anuken 71b1428fbe Fixed #12290 2026-07-05 10:43:47 -04:00
Anuken cbd3bea792 Merge remote-tracking branch 'origin/master' 2026-07-05 09:46:50 -04:00
Anuken e24d63c971 Fixed #12293 2026-07-05 09:46:44 -04:00
Anuken bdc4ed311c Update CONTRIBUTING.md 2026-07-04 14:29:38 -04:00
Anuken 05c3c856a9 Merge remote-tracking branch 'origin/master' 2026-07-04 13:01:31 -04:00
Anuken e58782c838 Bulk-serialization optimization 2026-07-04 13:01:24 -04:00
Kevin Vilyan 6ad776ca7a Fixed Minor Thing in Bundle ID (#12286) 2026-07-04 11:22:25 -04:00
Anuken 3c2004a2e7 Merge remote-tracking branch 'origin/master' 2026-07-04 11:18:12 -04:00
Anuken e3a877c948 Sync cleanup + player-local entities/labels 2026-07-04 11:18:07 -04:00
Github Actions 33814d2339 Automatic bundle update 2026-07-04 14:47:20 +00:00
Anuken c756faddac Fixed un-sanitized filenames being used in file chooser 2026-07-04 10:45:55 -04:00
Zoe Chen eed063af2f Update Chinese translations in bundle_zh_TW.properties (#12268) 2026-07-04 10:44:51 -04:00
BalaM314 382ca559eb Entity serialization optimization, part 1 (#12285)
* Share entity snapshots where possible

* Serialize per-team when FoW enabled

* small fixes

* PR review fixes

* don't spam toByteArray
* Keep snapshot timer in netServer, delete it from NetConnection and TeamData
* formatting
2026-07-04 10:44:32 -04:00
Github Actions e0ed93ed8a Automatic class mapping update 2026-07-04 00:51:28 +00:00
EggleEgg bb62a3163a drawNoise/drawNoiseLayers as an effect so that json can use them (#12152)
* drawNoise/drawNoiseLayers as an effect so that json can use them

* .* import

* dont call everytime

* use getOrNull

* probably still wrong somewhere

* just in case
2026-07-03 20:49:13 -04:00
CardillanandAnuken cc850dd75e Sensing heat (#12191)
* Sensing heat

* Returning null instead of 0 for turrets that do not use heat

* Apply suggestions from code review

Co-authored-by: Anuken <arnukren@gmail.com>

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-07-03 20:45:35 -04:00
kay 5ad9a65a15 unhardcode logic display background color (#12178) 2026-07-03 20:43:27 -04:00
2B2M22 c2103247ed Spawn on core doesnt ignore "possessionAllowed" rule (#12183)
* Make player cannot control building when possession disabled

* check is core best
2026-07-03 20:36:08 -04:00
Github Actions 6a6ed90473 Automatic bundle update 2026-07-04 00:33:11 +00:00
Anuken 478e3a2109 Merge remote-tracking branch 'origin/master' 2026-07-03 20:31:53 -04:00
Anuken cf1c08c66e Removed unused bundle entry 2026-07-03 20:31:46 -04:00
BalaM314 689d8c9e48 Blacklist UDP address along with TCP address (#12274) 2026-07-03 20:30:38 -04:00
Github Actions 3ff15ff7e9 Automatic bundle update 2026-07-04 00:27:00 +00:00
Pyratite No Lead 6d855fef24 Update Simplified Chinese Translation (#12215)
* Update Simplified Chinese translation

* Update Simplified Chinese translation 2

* Fix typo

* Revert "Fix typo"

This reverts commit 9a097d8e19.

* Fix typo

* Update Simplified Chinese Translation

* Update Simplified Chinese translation 2

* Fix typo

* Fix typo
2026-07-03 20:25:36 -04:00
Y-Yes 7b8347a9c2 Updated translations in bundle_lt.properties (#12248) 2026-07-03 20:24:11 -04:00
EggleEgg 713e796da6 Serpulo nano-rebalance: conveyor and junction (#11767) 2026-07-03 20:24:00 -04:00
Github Actions 780449edee Automatic bundle update 2026-07-04 00:23:52 +00:00
Sunky.MP3GandAnuken 2736ec96fb Ru translations (#12218)
* Update bundle_ru.properties

* Fall damage lololol

* forgot

* Update bundle_ru.properties

* Other

* Update bundle_ru.properties

* Fixed #12254

* Dev and patch stuff

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-07-03 20:22:37 -04:00
SITUVNgcdandAnuken 4691696afe Update Vietnamese translation (#12139)
* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/ed9ad45332397b58884ffd3d4c42db2a2b274a63

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/eae56c4230bf24ac6c732f31d46ca5acb1d85c78

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/e9c06482409d057a58a5952081c66bfe0f123846

* Update Vietnamese translation

https://github.com/Anuken/Mindustry/commit/2bdedfed25932ebf11330d3584092c50e2e26d96

---------

Co-authored-by: Anuken <arnukren@gmail.com>
2026-07-03 20:21:48 -04:00
alecthe2nd 66d0019063 Add icon formatting to content descriptions and details (#12266) 2026-07-03 20:21:06 -04:00
summoner 86683d60cd Translation: Update bundle_hu.properties (#12138)
* Translation: Update bundle_hu.properties

Translate new strings

* Translation: Update bundle_hu.properties

Translate new string

* Translation: Update bundle_hu.properties

Translate new string
Follow the changes of the english bundle

* Translation: Update bundle_hu.properties

Fix typo

* Translation: Update bundle_hu.properties

Translate new strings
Follow the changes of the english bundle
Fix translation

* Translation: Update bundle_hu.properties

Translate new strings

* Translation: Update bundle_hu.properties

Follow the changes of the english bundle

* Translation: Update bundle_hu.properties

Translate new strings
fix translation
Follow the changes of the english bundle

* Translation: Update bundle_hu.properties

Translate new strings

* Tranlastion: Update bundle_hu.properties

translate new strings
2026-07-03 20:20:43 -04:00
Kevin Vilyan 7b9f564f74 update bundle id (final) (#12147)
* Add files via upload

* decided to revision some texts

* unit fact activation

* update hideSpawns & revision campaign introduction

* minor revision

* game \-\ permainan

* data pacher new

* addition

* finish the messages

* revision

* screenshot error

* steamFriendsOnly

* Update bundle_id_ID.properties

* Some New Settings

* hmph
2026-07-03 20:20:28 -04:00
Anuken 9e2851aa0b Fixed ground zero unit kill objective 2026-07-03 13:51:39 -04:00
Anuken 9823981222 Merge branch 'sdl3' of https://github.com/Anuken/Mindustry into array-textures-sdl3 2026-07-02 17:07:46 -04:00
Anuken 69f7fbfbb2 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	gradle.properties
2026-07-02 15:41:49 -04:00
Anuken 1af06f58ce Merge remote-tracking branch 'origin/master' 2026-07-02 15:41:02 -04:00
Anuken 03abf9dc0d Fixed incorrect perf bar scaling 2026-07-02 15:40:56 -04:00
Anuken 4a2e76c415 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	gradle.properties
2026-07-02 10:15:54 -04:00
EggleEgg 12509e6225 Make all research prioritize resources outside of the currently active sector (#12153)
* Make all research prioritize resources outside of the currently active sector

* YOU DONT EVEN NEED THIS STOP IMPORTING RANDOM CLASSES

* hopefully I m not stupid enough to mess this up

* STOP IMPORTING

* did I screw up somewhere? who knows
2026-07-02 10:08:45 -04:00
Anuken 58e21f32b4 Fixed #12280 2026-07-02 10:06:10 -04:00
Anuken 735cb143ae Fixed #12276 2026-07-02 09:47:44 -04:00
Anuken 7b7c1190cf Merge remote-tracking branch 'origin/master' 2026-07-02 09:30:14 -04:00
Anuken f9fdbaae9b Fixed #12279 2026-07-02 09:30:07 -04:00
Github Actions bcb080aa42 Automatic class mapping update 2026-07-02 00:58:23 +00:00
Anuken 81b217dadc Assigned more accurate difficulty for submissions 2026-07-01 20:56:13 -04:00
Anuken e48790de77 Fixed some horrible JSON hacks 2026-07-01 13:57:53 -04:00
Anuken a4178e4c18 Fixed #12267 2026-07-01 01:36:58 -04:00
Anuken 5ae986a6dd Fixed #12270 2026-07-01 00:25:27 -04:00
Anuken a07ded343c Merge remote-tracking branch 'origin/master' 2026-06-29 23:10:40 -04:00
Anuken c990822abb Submission updates 2026-06-29 23:10:33 -04:00
EggleEgg dca67a8996 Bugfix: wreck/explosive damage bypassing shields (#12269) 2026-06-29 22:54:52 -04:00
Anuken dc2020f328 Updated rhino 2026-06-29 18:34:52 -04:00
Anuken 7370173f63 Show truncated stack trace in crash dialog 2026-06-28 21:40:15 -04:00
Anuken c423d24834 Updated several map submissions 2026-06-28 21:31:19 -04:00
Anuken 002541aa27 Force linear filtering for UI, as in main branch 2026-06-28 16:08:10 -04:00
Anuken beaed55c08 ...actually nevermind 2026-06-27 21:46:11 -04:00
Anuken 2e3491cd39 Additional registration fix 2026-06-27 21:45:50 -04:00
Anuken 3492446a73 Merge remote-tracking branch 'origin/array-textures' into array-textures 2026-06-27 21:45:26 -04:00
Anuken aa9f39f82f Fixed emojis on headless servers 2026-06-27 21:45:19 -04:00
Github Actions 0df2b4487f Automatic bundle update 2026-06-28 01:42:06 +00:00
Anuken 0a9d5c5005 Cleanup 2026-06-27 21:40:44 -04:00
Anuken d581160603 Added support for adding emojis in data patches / on servers 2026-06-27 21:40:00 -04:00
Anuken 364f5a8d9b Cleanup 2026-06-27 15:09:51 -04:00
Anuken 04c1aab69c Support for mod content icons in font 2026-06-27 14:13:48 -04:00
Anuken 12290b4d53 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	gradle.properties
2026-06-27 13:46:58 -04:00
Anuken a8f6222f0c WIP mod font icon support 2026-06-27 13:46:51 -04:00
Anuken b58bddbd03 Merge remote-tracking branch 'origin/master' 2026-06-27 12:20:18 -04:00
Anuken 2361f9a630 Fixed mismatched end() call 2026-06-27 12:20:12 -04:00
Github Actions 4334710289 Automatic bundle update 2026-06-27 15:44:43 +00:00
Anuken c764999d75 Toggleable performance metrics display 2026-06-27 11:43:24 -04:00
Anuken 6b416f7187 Moved unit updating to separate performance counter 2026-06-27 10:20:22 -04:00
Anuken b3b59a5f6a Shuffle servers on load + Crash fix 2026-06-26 17:26:17 -04:00
Anuken 5d252515e2 Merge remote-tracking branch 'origin/master' 2026-06-26 15:47:30 -04:00
Anuken 37ac3c9e70 ID check fix 2026-06-26 15:47:24 -04:00
Cardillan 32e95a69a9 Fix mod settings not displayed correctly (#12255) 2026-06-26 14:40:57 -04:00
NeilGreenFly c054ffeb2b Fix the issue where the icon for UnlockableContent characters in the text isn't centered on the character (#12262)
* Let the logic display enable allowRectanglePlacement.

* Fix the issue where the icon for UnlockableContent characters in the text isn't centered on the character
2026-06-26 14:40:01 -04:00
Anuken 027ea766e6 Clean previews on data import 2026-06-26 14:39:29 -04:00
Anuken 4e8a7d98af Fixed #12258 2026-06-26 14:38:49 -04:00
Anuken b50716362b Merge remote-tracking branch 'origin/master' 2026-06-26 14:31:06 -04:00
Anuken 4e57366960 Removed unused keybind 2026-06-26 14:31:00 -04:00
Github Actions 52822246e8 Automatic bundle update 2026-06-26 18:06:08 +00:00
Anuken 25c7067664 Key for teleporting to cursor in the editor 2026-06-26 14:04:36 -04:00
Anuken 6b89eabfee arc 2026-06-26 13:55:31 -04:00
Anuken 0571faa350 Less hacky editor building updates 2026-06-26 13:55:11 -04:00
Anuken c3785ed4fc Merged file chooser changes 2026-06-26 13:02:05 -04:00
Anuken 10b478b1bd Merge branch 'master' of https://github.com/Anuken/Mindustry into sdl3
# Conflicts:
#	desktop/src/mindustry/desktop/DesktopLauncher.java
2026-06-26 12:45:02 -04:00
Anuken e3da9fed6e Slightly more conservative max delta values 2026-06-26 12:37:49 -04:00
Anuken c74cfb63a6 More config for uuidChangeLimit 2026-06-26 12:11:10 -04:00
Anuken 90a6bf2508 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	gradle.properties
2026-06-26 12:02:34 -04:00
Anuken b1480d4270 Consistent toArray -> toSeq usage 2026-06-26 11:59:51 -04:00
Anuken 9b13d85b46 cleanup 2026-06-26 11:50:57 -04:00
Anuken 25a542759d Check for changing UUID many times on the same IP 2026-06-26 11:09:45 -04:00
Anuken 6d625167a5 arc 2026-06-26 10:33:05 -04:00
Anuken e453f3ccc7 Reverted the timestep revert 2026-06-25 02:34:36 -04:00
Anuken 2d1852470e Merge branch 'master' into fixed-timestep
# Conflicts:
#	core/src/mindustry/ui/dialogs/SettingsMenuDialog.java
2026-06-25 02:33:42 -04:00
Anuken 5ef7c8bce8 Reverted fixed timestep changes 2026-06-25 02:33:07 -04:00
Anuken 1afa757f3b default on fixed timestep 2026-06-25 02:27:49 -04:00
Anuken 692c4c65e4 cleanup 2026-06-25 02:18:24 -04:00
Anuken de5c858903 cleanup 2026-06-24 22:39:27 -04:00
Anuken 2effc25ad0 fixed timestep insanity 2026-06-24 19:45:10 -04:00
Anuken ca7f9662e2 Fixed some update bugs 2026-06-24 13:42:19 -04:00
Anuken b56d235233 Minor conveyor draw optimization 2026-06-24 13:02:38 -04:00
Anuken 60b4e9a0d7 Fixed duct updates/interpolation 2026-06-24 12:50:56 -04:00
Anuken 0e5d6d1252 Reverted buggy conveyor interpolation 2026-06-24 12:30:38 -04:00
Anuken 4da35f91d9 Moved ambient audio to new thread 2026-06-24 12:20:23 -04:00
Anuken e6b17adf3a wip 2026-06-24 11:01:29 -04:00
Anuken d22a2995a3 Merge remote-tracking branch 'origin/master' 2026-06-23 13:19:42 -04:00
Anuken 32dd187421 Fixed timestep interpolation for some blocks 2026-06-23 13:19:36 -04:00
Github Actions 2bdedfed25 Automatic bundle update 2026-06-22 21:57:37 +00:00
Anuken 9d967277cd Developer options + checkbox settings change + fixed building timestep option 2026-06-22 17:55:57 -04:00
Anuken d925a0a1b2 Moved entity updates into separate methods 2026-06-22 15:57:34 -04:00
Anuken b1135371ac arc 2026-06-22 12:26:29 -04:00
Anuken 40bf89df32 Merge remote-tracking branch 'origin/master' 2026-06-22 12:25:56 -04:00
Anuken 84d23af453 Fixed incorrect resource calculations 2026-06-22 12:25:49 -04:00
Cardillan 4e28dbbf09 Make read/write object fields wider (#12251) 2026-06-22 12:00:54 -04:00
Anuken 5ce1b5acb3 Fixed #12252 2026-06-22 11:52:19 -04:00
Anuken 0c31df6630 Fixed LOD for power nodes at max zoomout on mobile 2026-06-21 23:48:58 -04:00
Anuken 709ab337f1 Merge remote-tracking branch 'origin/array-textures' into array-textures 2026-06-21 22:20:35 -04:00
Anuken 9a71b203af Core extension refactor 2026-06-21 22:20:26 -04:00
Anuken 88b2f6e94e Cache handle check fix 2026-06-21 19:17:28 -04:00
Anuken 601034adfa Fixed zoom clipping into Erekir atmosphere 2026-06-21 17:58:25 -04:00
Anuken 919ffd4430 arc 2026-06-21 17:11:40 -04:00
Anuken f681ce9036 arc 2026-06-21 17:04:02 -04:00
Anuken b194fcbe2c Framebuffer refactor 2026-06-21 16:39:27 -04:00
Anuken b3f9fd9a71 Erekir planet shader adjustments 2026-06-21 15:20:33 -04:00
Anuken 3e84b28154 Shader reorganization & planet atmosphere depth fix 2026-06-21 14:45:56 -04:00
Anuken 61c96dbc67 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	core/assets-raw/sprites/blocks/environment/data-patch-reserved-env.png
2026-06-21 13:05:50 -04:00
Anuken 9147b69c3a Merge remote-tracking branch 'origin/master' 2026-06-21 13:02:27 -04:00
Anuken 2ecc7ff340 Raised minSdkVersion 14 -> 21 for Android due to NDK no longer supporting 14 2026-06-21 13:02:18 -04:00
Github Actions 991310be92 Automatic bundle update 2026-06-21 16:32:07 +00:00
Anuken 7359e05412 Misc bugfixes for data patches 2026-06-21 12:30:49 -04:00
Anuken f5133aa8e3 Support for autotiled destructible walls 2026-06-21 10:56:33 -04:00
Anuken 35306423b5 Fixed #12250 2026-06-21 10:07:52 -04:00
Anuken 6283c10cd7 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	core/src/mindustry/mod/DataImagePacker.java
#	gradle.properties
2026-06-21 09:53:08 -04:00
Anuken 69f95ee396 Stop trying to pack when env atlas is full 2026-06-21 09:52:10 -04:00
Anuken 559b64b3ac Fixed #12185 2026-06-20 21:53:38 -04:00
Anuken 4747ee35be Fixed #12209 2026-06-20 21:51:13 -04:00
Anuken ff84208703 Merge remote-tracking branch 'origin/master' 2026-06-20 21:43:56 -04:00
Anuken 1f1df02356 Fixed #12214 2026-06-20 21:43:51 -04:00
wan 143585bd39 Update bundle_ja.properties (#12246) 2026-06-20 21:29:50 -04:00
Anuken 59347a3de1 Fixed #12167 2026-06-20 21:29:10 -04:00
Anuken ac25174a95 Fixed #12198 2026-06-20 21:27:16 -04:00
Anuken b6b42bad9d Fixed #12148 2026-06-20 21:20:12 -04:00
Anuken ffffd5751d Fixed #12188 2026-06-20 21:10:37 -04:00
Anuken fc867d38e6 Fixed #12190 2026-06-20 21:05:04 -04:00
Anuken 9c98602f9a Fixed #12208 2026-06-20 21:00:46 -04:00
Anuken cc278a3a6e Fixed #12223 2026-06-20 20:53:41 -04:00
Anuken 2dd86456cf Fixed #12240 2026-06-20 20:48:09 -04:00
Anuken e43d2db0d6 Merge remote-tracking branch 'origin/master' 2026-06-20 20:29:29 -04:00
Anuken 33a8406bd3 Reverted #12243 2026-06-20 20:29:24 -04:00
EggleEgg 66be97ee47 Erekir nano-rebalance: small heat redirector buff (#12137)
* Erekir nano-rebalance: small heat redirector buff

* redirector original cost + 6 tung but acts like a node

* Just go for the easy option for now. 3 surge
2026-06-20 20:19:46 -04:00
buthed010203 45e44fd8bc Add dedicated steam server support (#12166)
* Add dedicated steam server support.

* Fixup

* Add cancel button
2026-06-20 20:18:27 -04:00
buthed010203 479b3854ba Refactor Call.label to use WorldLabel (#12164)
* Refactor Call.label to use WorldLabel

* Don't serialize duration
2026-06-20 20:17:28 -04:00
BalaM314 0293c2a3a8 Re-order tech tree to remove unnecessary prerequisites (#12179)
* Mass driver gated behind Tar Fields as intended, instead of Impact 0078
* Plastanium conveyor can be researched without thorium
2026-06-20 20:15:40 -04:00
Valera a10f4455f7 Made plans' animation framerate-independent (#12187)
A minor fix of InputHandler#drawOtherBuildPlans
2026-06-20 20:14:00 -04:00
Anuken a586a34f36 Merge remote-tracking branch 'origin/master' 2026-06-20 20:12:52 -04:00
Anuken fcf3f83737 Fixed unit assembler afterPatch 2026-06-20 20:12:46 -04:00
BalaM314 24adf22c53 Fix wiki builds failing (#12205) 2026-06-20 20:09:58 -04:00
StesNiash 0e4d0f6216 Update UnitAssembler.java (#12227)
Now units can payenter in assemblers.
2026-06-20 20:08:50 -04:00
Adham Hakki 3e4de7df52 Add mindustry:// URL scheme intent filter for Android (#12238) 2026-06-20 20:04:52 -04:00
NeilGreenFly ed130b1bac Let the logic display enable allowRectanglePlacement. (#12247) 2026-06-20 20:04:05 -04:00
Anuken 96e73c89d8 Merge branch 'master' of https://github.com/Anuken/Mindustry 2026-06-20 19:34:46 -04:00
Anuken b8fc1a70ed Reset public game visibility value to false because people keep making it public by accident 2026-06-20 19:34:44 -04:00
Github Actions 6175104b0e Automatic bundle update 2026-06-20 23:29:32 +00:00
Anuken d6400c573a Moved Steam hosting public checkbox to paused dialog + disabled global ban list in private lobbies 2026-06-20 19:28:09 -04:00
Anuken fe7f458a2f Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures 2026-06-20 17:33:49 -04:00
Anuken a96611a68c Merge remote-tracking branch 'origin/master' 2026-06-20 17:33:36 -04:00
Anuken aa82a26e1d Crash fix 2026-06-20 17:33:27 -04:00
Anuken dfcfabec66 Crash fix 2026-06-20 17:33:24 -04:00
ZenthXSinand488254306 04e74cba01 Fix NullPointerException in LogicBlock.updateLinks() when linksVar is null (#12241)
Co-authored-by: 488254306 <488254306@qq.com>
2026-06-20 16:35:56 -04:00
Wu Shuwen 7542587558 fix: skip unrecognized block IDs in client plan deserialization (#12244)
Prevent NullPointerException when a client sends a plan with a
block ID the server doesn't recognize (e.g. from a modded client).
Skip the plan entry instead of crashing.

Fixes #12243
2026-06-20 16:34:21 -04:00
Anuken 5a83175d96 Fixed NaN black screen after editor 2026-06-20 16:21:25 -04:00
Anuken e4ceff01d4 Fixed NaN black screen 2026-06-20 16:21:00 -04:00
Anuken 4f43020509 Removed accidental debug 2026-06-20 16:04:52 -04:00
Anuken e4d4b51962 Removed accidental debug 2026-06-20 16:04:34 -04:00
Anuken ff30daa79a Imports reorganized 2026-06-20 15:05:24 -04:00
Anuken 3d21e11360 Fixed planet rendering 2026-06-20 14:46:46 -04:00
Anuken 4856af4916 Refactoring to match newest Arc commit 2026-06-20 14:28:17 -04:00
Anuken 345750ac61 Merge branch 'master' of https://github.com/Anuken/Mindustry into array-textures
# Conflicts:
#	gradle.properties
2026-06-20 10:39:53 -04:00
Anuken 81841ad35a Merge remote-tracking branch 'origin/master' 2026-06-20 10:39:38 -04:00
Anuken 82d1df7445 Fixed quitting editor not resetting data patches 2026-06-20 10:39:32 -04:00
Anuken 13fecec653 Made data patches work with array textures 2026-06-19 23:24:30 -04:00
Anuken a4c87caa04 Misc fixes 2026-06-19 16:24:52 -04:00
Anuken c397c797ed Texture array progress 2026-06-19 15:12:10 -04:00
Anuken 8eacc17ce4 cleanup 2026-06-19 14:29:32 -04:00
Anuken 475746e75d WIP texture array refactor 2026-06-19 14:29:19 -04:00
Anuken 5c7e7074ba crash fix 2026-06-19 03:30:22 -04:00
Anuken d225eaf624 missing files 2026-06-19 03:27:15 -04:00
Anuken 1314db7295 WIP texture array sprite batch + gl3 min 2026-06-19 03:24:18 -04:00
Github Actions b7b8c61d47 Automatic class mapping update 2026-06-19 01:21:56 +00:00
Anuken 0672e7f37e Removed unused/broken block classes 2026-06-18 21:19:40 -04:00
Anuken 7f67b1dbce Misc minor fixes 2026-06-18 21:16:32 -04:00
Anuken 368e787f89 Hide editor when joining a game 2026-06-18 09:59:50 -04:00
Anuken de2cba940d Fixed node unlink not updating power graph 2026-06-18 09:50:47 -04:00
EggleEgg bdc7a62c39 linkSameType field for ItemBridge 2026-06-10 14:16:49 +02:00
Anuken d9d904a5c8 Merge branch 'master' of https://github.com/Anuken/Mindustry into sdl3
# Conflicts:
#	build.gradle
2026-05-28 10:38:51 -04:00
Adleanogare 7ee15b1ffd Merge branch 'master' into dob_json 2026-04-27 12:16:23 +02:00
Arthur Schifano 7f7117187e The global variable was still needed, for the button. 2026-04-18 22:57:50 +02:00
Arthur Schifano 3b4c78ca4a Patched a bug where when changing editor you could still copy a previous objective, leading to reference issue 2026-04-18 22:54:50 +02:00
Adleanogare 0d62cbd7c5 Merge branch 'master' into dob_json 2026-04-18 16:54:29 +02:00
Arthur Schifano 21d6494923 Adding the ctrl-c ctrl-v copy for keyboard device. The behaviour changed in some small ways. 2026-04-18 16:20:25 +02:00
Arthur Schifano a5d076decc The copy blocks now only appear for mobile. (Stilled need to be compilled and tested, desktop ctrl-c ctrl-v will come soon.) 2026-04-13 18:13:32 +02:00
Arthur Schifano 02ce0bc8a5 Slight change to text 2026-04-08 18:35:43 +02:00
Arthur Schifano fe5ca2614e Adding myself as a contributor if my pr is good enough 2026-04-08 17:54:24 +02:00
Arthur Schifano 066e1b39ab Adding a map objective copy/paste through the JSON copy mechanism 2026-04-08 17:40:03 +02:00
Anuken e1e9f886a3 Merge branch 'master' of https://github.com/Anuken/Mindustry into sdl3
# Conflicts:
#	core/assets/maps/serpulo/coastline.msav
#	core/src/mindustry/ui/dialogs/SettingsMenuDialog.java
#	gradle.properties
2026-04-07 11:16:09 -04:00
Anuken 66ea037add App name for SDL3 backend 2026-03-03 00:31:53 -05:00
Anuken 24c38894bb Fixed banned units on Coastline 2026-02-23 22:30:41 -05:00
Anuken dc1e36bcd2 Fixed objective team selection 2026-02-23 00:53:51 -05:00
Anuken 48d3fa1c11 Proper backend 2026-02-16 17:32:00 -05:00
Anuken 88e487303d Revert "SDL3 is broken, reverting to SDL2 (Closes #11671, #11676)"
This reverts commit 0580e1af
2026-02-16 17:31:06 -05:00
Anuken a6b29b854c Reapply "Removed borderless fullscreen option (window should always be borderless fullscreen anyway)"
This reverts commit a3682756dc.
2026-02-16 17:30:35 -05:00
Jason e5e19f0a44 Formatting
Signed-off-by: Jason <131086642+JasonP01@users.noreply.github.com>
2026-02-16 05:41:53 +02:00
JasonP01 6e43281ee4 Remove testing changes 2026-02-15 06:56:06 +02:00
JasonP01 394f6b8170 changes, needs revision 2026-02-15 06:52:31 +02:00
JasonP01 b8e9683c81 Rework status chance 2026-02-15 04:40:45 +02:00
Giovanni Ruotolo ca3b71d2b8 Merge branch 'master' into master 2026-02-13 15:54:50 +01:00
Giovanni Ruotolo 5dfd76427b micro fix 2026-02-13 15:52:16 +01:00
Giovanni Ruotolo e421b6f896 Full Italian localization
Complete and fix the Italian localization (file bundle_it.properties) align more with the original english one.
Added the translation for Android and Steam.
2026-02-12 13:37:44 +01:00
MEEPofFaith bb144185a1 Skip propagation if unnecessary 2025-11-04 16:54:55 -08:00
MEEPofFaith 947375ba52 Option for breaking props 2025-11-04 16:52:24 -08:00
MEEPofFaith c02fba3719 Explosion time switched to speed, optimize fire spread 2025-11-04 16:49:02 -08:00
MEEPofFaith 30d02787a6 Slower default time, don't apply to boulders 2025-11-04 13:10:37 -08:00
MEEPofFaith 2a360a8113 Explosion propagation time 2025-11-04 13:07:23 -08:00
MEEPofFaith e87687ea04 Break boulders 2025-11-04 12:49:54 -08:00
MEEPofFaith 9cafff14c6 Less 2025-11-04 12:34:20 -08:00
MEEPofFaith debae7c6a1 Tiny radius, raise chance 2025-11-04 12:32:15 -08:00
MEEPofFaith 11e3f522b3 Apply to generators 2025-11-04 12:30:32 -08:00
MEEPofFaith 5a3304d006 Better chance scaling 2025-11-04 12:21:25 -08:00
MEEPofFaith 515a3073d5 Ignition 2025-11-04 12:10:46 -08:00
MEEPofFaith 9d8168dbf5 Scorch effect 2025-11-04 12:03:07 -08:00
1813 changed files with 182997 additions and 27711 deletions
+10 -6
View File
@@ -1,5 +1,5 @@
name: Bug report
description: The type of device you were playing on
description: An issue with the game.
labels: ["bug"]
body:
@@ -43,17 +43,17 @@ body:
id: mods
attributes:
label: Mods used
description: The mod repositories or zip files that are related to the issue, if applicable.
description: The mod repositories or zip files that are related to the issue, if applicable. If you are positive that you have none enabled, write 'none'.
validations:
required: false
required: true
- type: textarea
id: save-file
attributes:
label: Save file
description: The (zipped) save file you were playing on when the bug happened. If this happened in the campaign, specify the sector, and attach the file you get from Settings -> Game Data -> Export Data. For custom games, attach the .msav file exported from the save dialog, zipped.
placeholder: THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME OR IN MULTIPLAYER, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME. IF YOU DO NOT HAVE A SAVE, DON'T WASTE TIME OPENING THIS ISSUE.
placeholder: THIS IS REQUIRED FOR ANY IN-GAME ISSUE. IF YOU DO NOT HAVE A SAVE, DO NOT WASTE TIME OPENING THIS ISSUE.
validations:
required: false
required: true
- type: textarea
id: logs
attributes:
@@ -72,5 +72,9 @@ body:
required: true
- label: I have searched the closed and open issues to make sure that this problem has not already been reported.
required: true
- label: "I am not using Foo's Client, and have made sure the bug is not caused by mods I have installed."
- label: "I am not using Foo's Client."
required: true
- label: "This issue occurs with no mods enabled."
required: true
- label: "I have attached a valid save file."
required: true
+3 -3
View File
@@ -1,5 +1,5 @@
If your pull request is **not** translation or serverlist-related, read the list of requirements below and check each box:
If your pull request is **not** translation-related, read the list of requirements below and check each box:
- [ ] I have read the [contribution guidelines](https://github.com/Anuken/Mindustry/blob/master/CONTRIBUTING.md).
- [ ] I have ensured that my code compiles, if applicable.
- [ ] I have ensured that any new features in this PR function correctly in-game, if applicable.
- [ ] I have ensured that any new features or fixes in this PR function correctly in-game, if applicable.
- [ ] I affirm that this code follows Mindustry's [AI policy](https://github.com/Anuken/Mindustry/blob/master/CONTRIBUTING.md#ai-policy).
@@ -0,0 +1,8 @@
# Container image that runs your code
FROM ubuntu:18.04
# Copies your code file from your action repository to the filesystem path `/` of the container
COPY entrypoint.sh /entrypoint.sh
# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["/entrypoint.sh"]
@@ -0,0 +1,5 @@
name: 'Build Linux Natives in Docker Container'
description: 'Build Linux Natives in Ubuntu 18.04 docker container'
runs:
using: 'docker'
image: 'Dockerfile'
+41
View File
@@ -0,0 +1,41 @@
#!/bin/sh -l
# ubuntu dockerfile is very minimal (only 122 packages are installed)
# need to install updated git (from official git ppa)
apt-get -q update
apt-get -yq install software-properties-common
add-apt-repository ppa:git-core/ppa -y
# install dependencies expected by other steps
apt-get -q update
apt-get -yq install git \
curl \
ca-certificates \
wget \
bzip2 \
zip \
unzip \
xz-utils \
sudo gnupg locales
# set Locale to en_US.UTF-8 (avoids hang during compilation)
locale-gen en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# add zulu apt repository - https://docs.azul.com/core/install/debian
curl -s https://repos.azul.com/azul-repo.key | gpg --dearmor -o /usr/share/keyrings/azul.gpg
echo "deb [signed-by=/usr/share/keyrings/azul.gpg] https://repos.azul.com/zulu/deb stable main" | tee /etc/apt/sources.list.d/zulu.list
apt-get -q update
# install zulu JDK and Java build tools
apt-get -yq install zulu17-jdk-headless
# Install cross-compilation toolchains
apt-get -yq --force-yes install gcc g++
apt-get -yq --force-yes install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross
apt-get -yq --force-yes install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross
apt-get -yq --force-yes install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu libc6-dev-riscv64-cross
# Build Linux natives
cd arc
./gradlew arc-core:jnigenBuildAllLinux --no-daemon
+3 -29
View File
@@ -14,40 +14,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- name: Set up JDK 17
uses: actions/setup-java@v1
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Add Arc release
run: |
git config --global user.email "actions@github.com"
git config --global user.name "Github Actions"
git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
cd ../Arc
git tag ${RELEASE_VERSION}
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/Arc ${RELEASE_VERSION};
cd ../Mindustry
- name: Update JITpack repo
run: |
cd ../
cp -r ./Mindustry ./MindustryJitpack
cd MindustryJitpack
git config --global user.name "Github Actions"
git config --global user.email "actions@github.com"
git clone --depth 1 https://github.com/Anuken/MindustryJitpack.git
rm -rf .git
cp -r ./MindustryJitpack/.git ./.git
rm -rf MindustryJitpack
rm -rf .github
rm README.md
git add .
git commit --allow-empty -m "Updating"
git tag ${RELEASE_VERSION}
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryJitpack ${RELEASE_VERSION}
cd ../Mindustry
- name: Create artifacts
run: |
./gradlew desktop:dist server:dist core:depsJar core:assetsJar core:mergedJavadoc -Pbuildversion=${RELEASE_VERSION:1}
@@ -6,5 +6,5 @@ jobs:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2
- uses: actions/checkout@v7
- uses: gradle/actions/wrapper-validation@v3
+68
View File
@@ -0,0 +1,68 @@
name: Build Natives
on: [workflow_dispatch]
jobs:
natives-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'recursive'
- name: Build Linux Natives in Docker Container
uses: ./.github/workflows/build-linux-natives
id: docker
- name: Upload natives
uses: actions/upload-artifact@v7
with:
name: Linux natives
path: |
arc/arc-core/build/natives
natives-windows-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
- name: Install dependencies
run: sudo apt install g++-mingw-w64 g++-mingw-w64-i686 g++-mingw-w64-x86-64 gcc-mingw-w64 gcc-mingw-w64-i686 gcc-mingw-w64-x86-64
- name: Set env
run: echo "NDK_HOME=$ANDROID_NDK_HOME" >> $GITHUB_ENV
- name: Build natives
working-directory: arc
run: |
./gradlew arc-core:jnigenBuildAllWindows arc-core:jnigenBuildAllAndroid
- name: Upload arc-core natives
uses: actions/upload-artifact@v7
with:
name: Windows and Android natives
path: |
arc/arc-core/build/natives
natives-mac:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
- name: Build natives
working-directory: arc
env:
MACOSX_DEPLOYMENT_TARGET: '10.9'
run: |
./gradlew arc-core:jnigenBuildAllMacOsX
- name: Upload natives
uses: actions/upload-artifact@v7
with:
name: MacOS natives
path: |
arc/arc-core/build/natives
+12 -8
View File
@@ -10,21 +10,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- name: Set up JDK 17
uses: actions/setup-java@v1
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
- name: Fetch latest Arc
run: git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
uses: gradle/actions/setup-gradle@v6
- name: Install client test dependencies
run: sudo apt-get update && sudo apt-get install -y xvfb libgl1-mesa-dri libglx-mesa0
- name: Run unit tests
run: ./gradlew tests:test --stacktrace --rerun
- name: Run unit tests and build JAR
- name: Run client tests
run: ./gradlew pack tests:clientTest
- name: Build JAR
run: ./gradlew desktop:dist
- name: Upload desktop JAR for testing
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: Desktop JAR (zipped)
name: Desktop JAR
archive: false
path: desktop/build/libs/Mindustry.jar
+13 -27
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v7
- name: Trigger BE build
if: ${{ github.repository == 'Anuken/Mindustry' }}
run: |
@@ -22,17 +22,16 @@ jobs:
git config --global user.name "Github Actions"
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds ${BNUM}
- name: Set up JDK 17
uses: actions/setup-java@v1
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: 17
- name: Fetch latest Arc
run: git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
uses: gradle/actions/setup-gradle@v6
- name: Update bundles
if: ${{ github.repository == 'Anuken/Mindustry' }}
run: |
./gradlew updateBundles
./gradlew -DcompileMethodParams updateBundles
if [ -n "$(git status --porcelain)" ]; then
git config --global user.name "Github Actions"
@@ -41,35 +40,22 @@ jobs:
git commit -m "Automatic bundle update"
git push
fi
- name: Update scripts and class mappings
- name: Update scripts, class mappings and map names
if: ${{ github.repository == 'Anuken/Mindustry' }}
run: |
./gradlew updateScripts
./gradlew -DcompileMethodParams updateScripts fixMaps
if [ -n "$(git status --porcelain)" ]; then
git config --global user.name "Github Actions"
git config --global user.email "actions@github.com"
git add core/assets/scripts/* core/src/mindustry/mod/ClassMap.java
git commit -m "Automatic class mapping update"
git add core/assets/maps/*
git commit -m "Automatic class mapping and map name update"
git push
fi
- name: Update JITpack repo
if: ${{ github.repository == 'Anuken/Mindustry' }}
run: |
git config --global user.name "Github Actions"
git config --global user.email "actions@github.com"
cd ../
cp -r ./Mindustry ./MindustryJitpack
cd MindustryJitpack
git clone --depth 1 https://github.com/Anuken/MindustryJitpack.git
rm -rf .git
cp -r ./MindustryJitpack/.git ./.git
rm -rf MindustryJitpack
rm -rf .github
rm README.md
git add .
git commit --allow-empty -m "Updating"
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryJitpack
cd ../Mindustry
- name: Run unit tests
run: ./gradlew tests:test --rerun --stacktrace
- name: Install client test dependencies
run: sudo apt-get update && sudo apt-get install -y xvfb libgl1-mesa-dri libglx-mesa0
- name: Run client tests
run: ./gradlew pack tests:clientTest
+18 -10
View File
@@ -4,9 +4,6 @@ This is for code contributions. For translations, see [TRANSLATING](TRANSLATING.
## Basic Guidelines
### Use an IDE.
Specifically, IntelliJ IDEA. Download the (free) Community Edition of it [here](https://www.jetbrains.com/idea/download/). Some people use other tools, like VS Code, but I would personally not recommend them for Java development.
### Always test your changes.
Do not submit something without at least running the game to see if it compiles.
If you are submitting a new block, make sure it has a name and description, and that it works correctly in-game. If you are changing existing block mechanics, test them out first.
@@ -20,11 +17,19 @@ Yes, there are occurrences of trailing spaces, extra newlines, empty indents, an
I **especially** do not want to see PRs that apply any kind of automated analysis to the source code to "optimize" anything - my IDE can do that already. If the PR doesn't actually change anything useful, I'm not going to review or merge it.
### Do not make AI "contributions".
## AI Policy
If I see a PR with significant amounts of code that's obviously written by AI, I will reject your PR, and you will be blocked. Don't waste my time with slop.
Mindustry's AI contribution policies are similar to that of [the Rust language](https://forge.rust-lang.org/policies/llm-usage.html), which are summarized as follows:
Asking AI questions, and using that information to help you write code? Fine. Using it to actually write code? No.
- ✔️ You **are** allowed use AI to review your own code, summarize, inform, and answer questions.
- ✔️ You **are** allowed to use AI to translate your *human-written* messages into English, if necessary.
- ❌ You are **not** allowed to submit PRs that are generated by AI.
- ❌ You are **not** allowed to use AI to *generate* any text posted (PRs, issues, commit messages, etc.)
- ⚠️ If you post *anything* that is based on AI output (potential solution to a bug, crash diagnosis...), it must be clearly marked as being sourced from AI.
Repeated (or particularly egregious) violations of these rules will get you banned from this repository.
## Style Guidelines
@@ -34,7 +39,7 @@ This means:
- Same-line braces.
- 4 spaces indentation
- `camelCase`, **even for constants or enums**. Why? Because `SCREAMING_CASE` is ugly, annoying to type and does not achieve anything useful. Constants are *less* dangerous than variables, not more. Any reasonable IDE should highlight them for you anyway.
- No underscores for anything. (Yes, I know `Bindings` violates this principle, but that's for legacy reasons and really should be cleaned up some day)
- No underscores for anything.
- Do not use braceless `if/else` statements. `if(x) statement else statement2` should **never** be done. In very specific situations, having braceless if-statements on one line is allowed: `if(cond) return;` would be valid.
- Prefer single-line javadoc `/** @return for example */` instead of multiline javadoc whenever possible
- Short method/variable names (multipleLongWords should be avoided if it's possible to do so reasonably, especially for variables)
@@ -67,7 +72,6 @@ What you'll usually need to change:
### Avoid boxed types (Integer, Boolean)
Never create variables or collections with boxed types `Seq<Integer>` or `ObjectMap<Integer, ...>`. Use the collections specialized for this task, e.g. `IntSeq` and `IntMap`.
### Do not allocate anything if possible.
Never allocate `new` objects in the main loop. If you absolutely require new objects, use `Pools` to obtain and free object instances.
Otherwise, use the `Tmp` variables for things like vector/shape operations, or create `static` variables for re-use.
@@ -77,9 +81,13 @@ If using a list, make it a static variable and clear it every time it is used. R
This is situational, but in essence, what it means is to avoid using any sort of getters and setters unless absolutely necessary. Public or protected fields should suffice for most things.
If something needs to be encapsulated in the future, IntelliJ can handle it with a few clicks.
### Do not create methods unless necessary.
Unless a block of code is very large or used in more than 1-2 places, don't split it up into a separate method. Making unnecessary methods only creates confusion, and may slightly decrease performance.
## Other Notes
If you would like your name to appear in the game's credits, add it to the [list of contributors](https://github.com/Anuken/Mindustry/blob/master/core/assets/contributors) as part of your PR.
- If you would like your name to appear in the game's credits, add it to the [list of contributors](https://github.com/Anuken/Mindustry/blob/master/core/assets/contributors) as part of your PR.
- Using an IDE is highly recommended, but not required.
- I use IntelliJ; download it [here](https://www.jetbrains.com/idea/download/).
- Some people use other tools, like VS Code, but I haven't used them for Java myself, and cannot guarantee that they will work well for this codebase.
-3
View File
@@ -1,3 +0,0 @@
# Note: The v7 server list is frozen. No new servers will be accepted. All v8 server PRs should be made [here](https://github.com/Anuken/MindustryServerList).
*PRs to edit addresses of existing servers will still be accepted, although very infrequently.*
+30 -2
View File
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
<uses-feature android:glEsVersion="0x00030000" android:required="true"/>
<uses-feature android:name="android.hardware.type.pc" android:required="false" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:enableOnBackInvokedCallback="false"
android:resizeableActivity="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
@@ -24,13 +25,40 @@
android:label="@string/app_name"
android:screenOrientation="user"
android:exported="true"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout">
android:launchMode="singleTask"
android:configChanges="uiMode|keyboard|keyboardHidden|orientation|screenSize|screenLayout">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="mindustry"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="application/octet-stream" />
<data android:mimeType="application/x-msav" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:host="*" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.msav" />
</intent-filter>
</activity>
</application>
-166
View File
@@ -1,166 +0,0 @@
buildscript{
repositories{
mavenLocal()
mavenCentral()
google()
}
dependencies{
classpath 'com.android.tools.build:gradle:8.2.2'
}
}
apply plugin: "com.android.application"
configurations{ natives }
repositories{
mavenCentral()
maven{ url = "https://maven.google.com" }
}
task deploy(type: Copy){
dependsOn "assembleRelease"
from "build/outputs/apk/release/android-release.apk"
into "../deploy/"
rename("android-release.apk", "${generateDeployName('android')}.apk")
}
android{
namespace = "io.anuke.mindustry"
buildToolsVersion = '36.0.0'
compileSdk = 36
sourceSets{
main{
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets', 'src/main/assets', '../core/assets/']
if(localArc){
jniLibs.srcDirs += ['../../Arc/natives/natives-android/libs', '../../Arc/natives/natives-freetype-android/libs']
}else{
jniLibs.srcDirs = ['libs']
}
}
androidTest.setRoot('tests')
}
packagingOptions{
exclude 'META-INF/robovm/ios/robovm.xml'
}
defaultConfig{
Properties props = loadVersionProps()
Integer vcode = props['androidBuildCode']?.toInteger() ?: 1
def versionNameResult = "$versionNumber-$versionType-${getBuildVersion().replace(" ", "-")}"
applicationId "io.anuke.mindustry"
minSdkVersion 14
targetSdkVersion 36
versionName versionNameResult
versionCode = vcode
if(project.hasProperty("release")){
props['androidBuildCode'] = (vcode + 1).toString()
}
props.store(file('../core/assets/version.properties').newWriter(), null)
multiDexEnabled = true
}
compileOptions{
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
flavorDimensions = ["google"]
signingConfigs{
release{
if(project.hasProperty("RELEASE_STORE_FILE")){
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}else if(System.getenv("CI") == "true"){
storeFile = file("../../bekeystore.jks")
storePassword = System.getenv("keystore_password")
keyAlias = System.getenv("keystore_alias")
keyPassword = System.getenv("keystore_alias_password")
}else{
println("No keystore property found. Releases will be unsigned.")
}
}
}
buildTypes{
all{
//TODO without these lines (r8 enabled), Mindustry crashes with missing default interface method errors.
//WHY THE HELL ARE DEFAULT INTERFACES NOT BEING DESUGARED? WHY DID UPDATING AGP MAKE THIS HAPPEN?
//When I ENABLE shrinking, r8 goes and REMOVES ALL DEFAULT INTERFACE CLASSES, which breaks mods. Why?
//-keep class mindustry.** { *; } should *keep the classes* - WHY IS R8 REMOVING THEM?
minifyEnabled = true
shrinkResources = true
proguardFiles("proguard-rules.pro")
}
}
if(project.hasProperty("RELEASE_STORE_FILE") || System.getenv("CI") == "true"){
buildTypes{
release{
signingConfig = signingConfigs.release
}
}
}
}
dependencies{
implementation project(":core")
implementation arcModule("backends:backend-android")
implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3'
if(!localArc){
natives "com.github.Anuken.Arc:natives-android:$arcHash"
natives "com.github.Anuken.Arc:natives-freetype-android:$arcHash"
}
def version, highestVersion
new File((String)findSdkDir(), "/platforms").eachFileMatch ~/android-\d+/, {
version = it.name.find(/\d+/).toInteger()
highestVersion = version > highestVersion ? version : highestVersion
}
def sdkFile = new File((String)findSdkDir(), "/platforms/android-${highestVersion}/android.jar")
if(sdkFile.exists()) compileOnly files(sdkFile.absolutePath)
}
task copyAndroidNatives(){
if(!localArc){
configurations.natives.files.each{ jar ->
copy{
from zipTree(jar)
into file("libs/")
include "**"
}
}
}
}
task run(type: Exec){
commandLine "${findSdkDir()}/platform-tools/adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/mindustry.android.AndroidLauncher'
}
if(!project.ext.hasSprites()){
tasks.whenTaskAdded{ task ->
if(task.name == 'assembleDebug' || task.name == 'assembleRelease'){
task.dependsOn ":tools:pack"
}
}
}
+148
View File
@@ -0,0 +1,148 @@
import java.util.*
plugins{
id("com.android.application")
}
evaluationDependsOn(":core")
val versionNumber = providers.gradleProperty("versionNumber").get()
val versionType = providers.gradleProperty("versionType").get()
val buildVersion = rootProject.extra["buildVersion"] as String
val hasSprites = rootProject.extra["hasSprites"] as Boolean
@Suppress("UNCHECKED_CAST")
val deployName = rootProject.extra["deployName"] as (String) -> String
val versionPropsFile = rootProject.file("core/assets/version.properties")
fun loadVersionProps(): Properties =
Properties().also{ props -> versionPropsFile.bufferedReader().use{ props.load(it) } }
fun findSdkDir(): String?{
System.getenv("ANDROID_HOME")?.let{ return it }
val props = Properties().also{ p -> File(rootDir, "local.properties").bufferedReader().use{ p.load(it) } }
return props.getProperty("sdk.dir")
}
repositories{
google()
}
fun MutableCollection<String>.only(vararg paths: String){
clear()
addAll(paths)
}
tasks.register<Copy>("deploy"){
dependsOn("assembleRelease")
from("build/outputs/apk/release/android-release.apk")
into("../deploy/")
rename("android-release.apk", "${deployName("android")}.apk")
}
android{
namespace = "io.anuke.mindustry"
compileSdk = 36
sourceSets{
getByName("main"){
manifest.srcFile("AndroidManifest.xml")
java.directories.only("src")
aidl.directories.only("src")
renderscript.directories.only("src")
res.directories.only("res")
assets.directories.only("assets", "src/main/assets", "../core/assets/")
jniLibs.directories.only("../arc/natives/natives-android/libs")
}
getByName("androidTest").setRoot("tests")
}
packaging{
resources{
excludes += "META-INF/robovm/ios/robovm.xml"
}
}
defaultConfig{
val props = loadVersionProps()
val vcode = props.getProperty("androidBuildCode")?.toInt() ?: 1
val versionNameResult = "$versionNumber-$versionType-${buildVersion.replace(" ", "-")}"
applicationId = "io.anuke.mindustry"
minSdk = 21
targetSdk = 36
versionName = versionNameResult
versionCode = vcode
if(project.hasProperty("release")){
props["androidBuildCode"] = (vcode + 1).toString()
}
versionPropsFile.bufferedWriter().use{ props.store(it, null) }
multiDexEnabled = true
}
compileOptions{
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
signingConfigs{
create("release"){
if(project.hasProperty("RELEASE_STORE_FILE")){
storeFile = file(project.property("RELEASE_STORE_FILE") as String)
storePassword = project.property("RELEASE_STORE_PASSWORD") as String
keyAlias = project.property("RELEASE_KEY_ALIAS") as String
keyPassword = project.property("RELEASE_KEY_PASSWORD") as String
}else if(System.getenv("CI") == "true"){
storeFile = file("../../bekeystore.jks")
storePassword = System.getenv("keystore_password")
keyAlias = System.getenv("keystore_alias")
keyPassword = System.getenv("keystore_alias_password")
}else{
println("No keystore property found. Releases will be unsigned.")
}
}
}
buildTypes{
all{
//TODO without these lines (r8 enabled), Mindustry crashes with missing default interface method errors.
//WHY THE HELL ARE DEFAULT INTERFACES NOT BEING DESUGARED? WHY DID UPDATING AGP MAKE THIS HAPPEN?
//When I ENABLE shrinking, r8 goes and REMOVES ALL DEFAULT INTERFACE CLASSES, which breaks mods. Why?
//-keep class mindustry.** { *; } should *keep the classes* - WHY IS R8 REMOVING THEM?
isMinifyEnabled = true
isShrinkResources = true
proguardFiles("proguard-rules.pro")
}
if(project.hasProperty("RELEASE_STORE_FILE") || System.getenv("CI") == "true"){
getByName("release"){
signingConfig = signingConfigs.getByName("release")
}
}
}
}
dependencies{
implementation(project(":core"))
implementation("com.github.Anuken:backend-android:frog")
implementation("com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3")
}
tasks.register<Exec>("run"){
commandLine("${findSdkDir()}/platform-tools/adb", "shell", "am", "start", "-n", "io.anuke.mindustry/mindustry.android.AndroidLauncher")
}
if(!hasSprites){
tasks.configureEach{
if(name == "assembleDebug" || name == "assembleRelease"){
dependsOn(":tools:pack")
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

@@ -2,4 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
</adaptive-icon>
@@ -2,4 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -16,8 +16,7 @@ import arc.struct.*;
import arc.util.*;
import dalvik.system.*;
import mindustry.*;
import mindustry.game.Saves.*;
import mindustry.io.*;
import mindustry.game.EventType.*;
import mindustry.net.*;
import mindustry.ui.*;
import mindustry.ui.FileChooser.*;
@@ -173,6 +172,15 @@ public class AndroidLauncher extends AndroidApplication{
throw new ArcRuntimeException(e);
}
}
@Override
public Writer writer(boolean append, String charset){
try{
return new OutputStreamWriter(write(append), charset);
}catch(IOException ex){
throw new ArcRuntimeException(ex);
}
}
}).toArray(Fi.class);
Core.app.post(() -> Core.app.post(() -> params.handleChooseResult(files)));
@@ -211,9 +219,10 @@ public class AndroidLauncher extends AndroidApplication{
}, new AndroidApplicationConfiguration(){{
useImmersiveMode = true;
hideStatusBar = true;
useGL30 = true;
}});
checkFiles(getIntent());
var intent = getIntent();
Events.on(ClientLoadEvent.class, u -> handleIntent(intent));
try{
//new external folder
@@ -271,54 +280,45 @@ public class AndroidLauncher extends AndroidApplication{
}
}
private void checkFiles(Intent intent){
@Override
protected void onNewIntent(Intent intent){
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent){
if(intent == null) return;
try{
Uri uri = intent.getData();
if(uri != null){
File myFile = null;
String scheme = uri.getScheme();
if(scheme.equals("file")){
String fileName = uri.getEncodedPath();
myFile = new File(fileName);
}else if(!scheme.equals("content")){
//error
return;
}
boolean save = uri.getPath().endsWith(saveExtension);
boolean map = uri.getPath().endsWith(mapExtension);
InputStream inStream;
if(myFile != null) inStream = new FileInputStream(myFile);
else inStream = getContentResolver().openInputStream(uri);
Core.app.post(() -> Core.app.post(() -> {
if(save){ //open save
System.out.println("Opening save.");
Fi file = Core.files.local("temp-save." + saveExtension);
file.write(inStream, false);
if(SaveIO.isSaveValid(file)){
try{
SaveSlot slot = control.saves.importSave(file);
ui.load.runLoadSave(slot);
}catch(IOException e){
ui.showException("@save.import.fail", e);
}
}else{
ui.showErrorMessage("@save.import.invalid");
}
}else if(map){ //open map
Fi file = Core.files.local("temp-map." + mapExtension);
file.write(inStream, false);
//clear data (not sure if necessary?)
intent.setAction(Intent.ACTION_MAIN);
intent.setData(null);
setIntent(intent);
if("mindustry".equalsIgnoreCase(scheme)){ //open a server URL
String host = uri.getHost();
int port = uri.getPort();
if(host != null && !host.isEmpty()){
Core.app.post(() -> {
System.out.println("Opening map.");
if(!ui.editor.isShown()){
ui.editor.show();
}
ui.editor.beginEditMap(file);
ui.showConfirm(Core.bundle.format("servers.connect.confirm", host), () -> ui.join.connect(host, port != -1 ? port : 6567));
});
}
}));
}else{ //open a save file
Fi file = Core.files.cache("imported");
file.write(getContentResolver().openInputStream(uri), false);
ClientLauncher.handleFileImport(file);
}
}
}catch(IOException e){
e.printStackTrace();
}catch(Throwable e){
Log.err(e);
}
}
@@ -2,9 +2,7 @@ package mindustry.android;
import android.annotation.*;
import android.os.*;
import android.os.Build.*;
import arc.*;
import arc.backend.android.*;
import com.android.dex.*;
import com.android.dx.cf.direct.*;
import com.android.dx.command.dexer.*;
@@ -13,7 +11,6 @@ import com.android.dx.dex.cf.*;
import com.android.dx.dex.file.DexFile;
import com.android.dx.merge.*;
import dalvik.system.*;
import mindustry.mod.*;
import rhino.*;
import java.io.*;
@@ -159,8 +156,9 @@ public class AndroidRhinoContext{
}catch(IOException e){
e.printStackTrace();
}
android.content.Context context = (android.content.Context)((AndroidApplication)Core.app);
return new DexClassLoader(dexFile.getPath(), VERSION.SDK_INT >= 21 ? context.getCodeCacheDir().getPath() : context.getCacheDir().getAbsolutePath(), null, getParent()).loadClass(name);
var context = (android.content.Context)Core.app;
return new DexClassLoader(dexFile.getPath(), context.getCodeCacheDir().getPath(), null, getParent()).loadClass(name);
}
@Override
-2
View File
@@ -1,2 +0,0 @@
sourceSets.main.java.srcDirs = ["src/main/java/"]
sourceSets.main.resources.srcDirs = ["src/main/resources/"]
+35
View File
@@ -0,0 +1,35 @@
plugins{
`java-library`
}
sourceSets.main{
java.setSrcDirs(listOf("src/main/java/"))
resources.setSrcDirs(listOf("src/main/resources/"))
}
dependencies{
implementation("com.squareup:javapoet:1.13.0")
implementation("com.github.Anuken:arc-core:frog")
}
tasks.withType<JavaCompile>().configureEach{
options.isFork = true
options.compilerArgs.addAll(
listOf(
"--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED",
"--add-exports", "jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"--add-exports", "java.base/sun.reflect.annotation=ALL-UNNAMED"
)
)
}
@@ -85,6 +85,7 @@ public class Annotations{
@Retention(RetentionPolicy.SOURCE)
public @interface GroupDef{
Class[] value();
Class[] exclude() default {};
boolean collide() default false;
boolean spatial() default false;
boolean mapping() default false;
@@ -211,10 +211,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
if(round++ >= rounds) return false; //only process 1 round
if(rootDirectory == null){
try{
String path = Fi.get(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no")
.toUri().toURL().toString().substring(OS.isWindows ? 6 : "file:".length()))
.parent().parent().parent().parent().parent().parent().parent().toString().replace("%20", " ");
rootDirectory = Fi.get(path).parent();
rootDirectory = new Fi(new File(filer.getResource(StandardLocation.CLASS_OUTPUT, "no", "no").toUri())).parent().parent().parent().parent().parent().parent().parent().parent();
}catch(IOException e){
throw new RuntimeException(e);
}
@@ -40,8 +40,6 @@ public class EntityIO{
this.serializer = serializer;
this.name = name;
json.setIgnoreUnknownFields(true);
directory.mkdirs();
//load old revisions
@@ -236,11 +234,11 @@ public class EntityIO{
if(BaseProcessor.isPrimitive(type)){
s(type.equals("boolean") ? "bool" : type.charAt(0) + "", field);
}else if(instanceOf(type, "mindustry.ctype.Content") && !type.equals("mindustry.ai.UnitStance") && !type.equals("mindustry.ai.UnitCommand")){
}else if(instanceOf(type, "mindustry.type.Content") && !type.equals("mindustry.ai.UnitStance") && !type.equals("mindustry.ai.UnitCommand")){
if(write){
s("s", field + " == null ? -1 : " + field + ".id");
}else{
st(field + "mindustry.Vars.content.getByID(mindustry.ctype.ContentType.$L, read.s())", BaseProcessor.simpleName(type).toLowerCase().replace("type", ""));
st(field + "mindustry.Vars.content.getByID(mindustry.type.ContentType.$L, read.s())", BaseProcessor.simpleName(type).toLowerCase().replace("type", ""));
}
}else if((serializer.writers.containsKey(type) || (network && serializer.netWriters.containsKey(type))) && write){
st("$L(write, $L)", network ? serializer.getNetWriter(type, null) : serializer.writers.get(type), field);
@@ -20,6 +20,7 @@ import javax.lang.model.element.*;
import javax.lang.model.type.*;
import java.lang.annotation.*;
import java.util.*;
import java.util.regex.*;
@SupportedAnnotationTypes({
"mindustry.annotations.Annotations.EntityDef",
@@ -29,6 +30,11 @@ import java.util.*;
"mindustry.annotations.Annotations.TypeIOHandler"
})
public class EntityProcess extends BaseProcessor{
static final Pattern selfParamPattern = Pattern.compile("this\\.<(.*)>self\\(\\)");
static final Pattern selfPattern = Pattern.compile("self\\(\\)");
static final Pattern yieldPattern = Pattern.compile(" yield ");
static final Pattern missingPattern = Pattern.compile("\\/\\*missing\\*\\/");
Seq<EntityDefinition> definitions = new Seq<>();
Seq<GroupDefinition> groupDefs = new Seq<>();
Seq<Stype> baseComponents;
@@ -77,12 +83,12 @@ public class EntityProcess extends BaseProcessor{
for(Smethod elem : component.methods()){
if(elem.is(Modifier.ABSTRACT) || elem.is(Modifier.NATIVE)) continue;
//get all statements in the method, store them
methodBlocks.put(elem.descString(), elem.tree().getBody().toString()
.replaceAll("this\\.<(.*)>self\\(\\)", "this") //fix parameterized self() calls
.replaceAll("self\\(\\)", "this") //fix self() calls
.replaceAll(" yield ", "") //fix enchanced switch
.replaceAll("\\/\\*missing\\*\\/", "var") //fix vars
);
String body = elem.tree().getBody().toString();
body = selfParamPattern.matcher(body).replaceAll("this"); //fix parameterized self() calls
body = selfPattern.matcher(body).replaceAll("this"); //fix self() calls
body = yieldPattern.matcher(body).replaceAll(""); //fix enhanced switch
body = missingPattern.matcher(body).replaceAll("var"); //fix vars
methodBlocks.put(elem.descString(), body);
}
}
@@ -234,15 +240,21 @@ public class EntityProcess extends BaseProcessor{
return result;
});
Seq<Stype> exclusions = types(an, GroupDef::exclude).map(stype -> {
Stype result = interfaceToComp(stype);
if(result == null) throw new IllegalArgumentException("Interface " + stype + " does not have an associated component!");
return result;
});
//representative component type
Stype repr = types.first();
String groupType = repr.annotation(Component.class).base() ? baseName(repr) : interfaceName(repr);
String name = group.name().startsWith("g") ? group.name().substring(1) : group.name();
String name = group.name();
boolean collides = an.collide();
groupDefs.add(new GroupDefinition(name,
ClassName.bestGuess(packageName + "." + groupType), types, an.spatial(), an.mapping(), collides, an.update()));
ClassName.bestGuess(packageName + "." + groupType), types, exclusions, an.spatial(), an.mapping(), collides, an.update()));
TypeSpec.Builder accessor = TypeSpec.interfaceBuilder("IndexableEntity__" + name);
accessor.addMethod(MethodSpec.methodBuilder("setIndex__" + name).addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).addParameter(int.class, "index").returns(void.class).build());
@@ -258,7 +270,9 @@ public class EntityProcess extends BaseProcessor{
//all component classes (not interfaces)
Seq<Stype> components = allComponents(type);
Seq<GroupDefinition> groups = groupDefs.select(g -> (!g.components.isEmpty() && !Structs.contains(ann.excludeGroups(), g.name) && !g.components.contains(s -> !components.contains(s))) || g.manualInclusions.contains(type));
Seq<GroupDefinition> groups = groupDefs.select(g -> (!g.components.isEmpty() && !Structs.contains(ann.excludeGroups(), g.name)
&& !g.components.contains(s -> !components.contains(s)) && !g.excludedComponents.contains(s -> components.contains(s))));
ObjectMap<String, Seq<Smethod>> methods = new ObjectMap<>();
ObjectMap<FieldSpec, Svar> specVariables = new ObjectMap<>();
ObjectSet<String> usedFields = new ObjectSet<>();
@@ -489,10 +503,10 @@ public class EntityProcess extends BaseProcessor{
for(GroupDefinition def : groups){
if(first.name().equals("add")){
//remove/add from each group, assume imported
mbuilder.addStatement("index__$L = Groups.$L.addIndex(this)", def.name, def.name);
mbuilder.addStatement("index__$L = mindustry.Vars.state.entities.$L.addIndex(this)", def.name, def.name);
}else{
//remove/add from each group, assume imported
mbuilder.addStatement("Groups.$L.removeIndex(this, index__$L);", def.name, def.name);
mbuilder.addStatement("mindustry.Vars.state.entities.$L.removeIndex(this, index__$L);", def.name, def.name);
mbuilder.addStatement("index__$L = -1", def.name);
}
@@ -558,7 +572,15 @@ public class EntityProcess extends BaseProcessor{
String blockName = elem.up().getSimpleName().toString().toLowerCase().replace("comp", "");
//skip empty blocks
if(str.replace("{", "").replace("\n", "").replace("}", "").replace("\t", "").replace(" ", "").isEmpty()){
boolean empty = true;
for(int i = 0; i < str.length(); i++){
char c = str.charAt(i);
if(c != '{' && c != '}' && c != '\n' && c != '\t' && c != ' '){
empty = false;
break;
}
}
if(empty){
continue;
}
@@ -582,7 +604,7 @@ public class EntityProcess extends BaseProcessor{
//add free code to remove methods - always at the end
//this only gets called next frame.
if(first.name().equals("remove") && ann.pooled()){
mbuilder.addStatement("mindustry.gen.Groups.queueFree(($T)this)", Poolable.class);
mbuilder.addStatement("mindustry.Vars.state.entities.queueFree(($T)this)", Poolable.class);
}
if(!legacy || specialIO){
@@ -638,17 +660,17 @@ public class EntityProcess extends BaseProcessor{
definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs, legacy));
}
//generate groups
TypeSpec.Builder groupsBuilder = TypeSpec.classBuilder("Groups").addModifiers(Modifier.PUBLIC);
MethodSpec.Builder groupInit = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
//generate entities, the per-state container of all groups
TypeSpec.Builder groupsBuilder = TypeSpec.classBuilder("Entities").addModifiers(Modifier.PUBLIC);
MethodSpec.Builder groupInit = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC);
for(GroupDefinition group : groupDefs){
//class names for interface/group
ClassName itype = group.baseType;
ClassName groupc = ClassName.bestGuess("mindustry.entities.EntityGroup");
TypeName groupType = ParameterizedTypeName.get(groupc, itype);
//add field...
groupsBuilder.addField(ParameterizedTypeName.get(
ClassName.bestGuess("mindustry.entities.EntityGroup"), itype), group.name, Modifier.PUBLIC, Modifier.STATIC);
groupsBuilder.addField(groupType, group.name, Modifier.PUBLIC);
groupInit.addStatement("$L = new $T<>($L.class, $L, $L, (e, pos) -> { if(e instanceof $L.IndexableEntity__$L ix) ix.setIndex__$L(pos); })", group.name, groupc, itype, group.spatial, group.mapping, packageName, group.name, group.name);
}
@@ -656,9 +678,9 @@ public class EntityProcess extends BaseProcessor{
//write the groups
groupsBuilder.addMethod(groupInit.build());
groupsBuilder.addField(boolean.class, "isClearing", Modifier.PUBLIC, Modifier.STATIC);
groupsBuilder.addField(boolean.class, "isClearing", Modifier.PUBLIC);
MethodSpec.Builder groupClear = MethodSpec.methodBuilder("clear").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
MethodSpec.Builder groupClear = MethodSpec.methodBuilder("clear").addModifiers(Modifier.PUBLIC);
groupClear.addStatement("isClearing = true");
for(GroupDefinition group : groupDefs){
groupClear.addStatement("$L.clear()", group.name);
@@ -669,11 +691,11 @@ public class EntityProcess extends BaseProcessor{
groupsBuilder.addMethod(groupClear.build());
//add method for pool storage
groupsBuilder.addField(FieldSpec.builder(ParameterizedTypeName.get(Seq.class, Poolable.class), "freeQueue", Modifier.PRIVATE, Modifier.STATIC).initializer("new Seq<>()").build());
groupsBuilder.addField(FieldSpec.builder(ParameterizedTypeName.get(Seq.class, Poolable.class), "freeQueue", Modifier.PRIVATE).initializer("new Seq<>()").build());
//method for freeing things
MethodSpec.Builder groupFreeQueue = MethodSpec.methodBuilder("queueFree")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addModifiers(Modifier.PUBLIC)
.addParameter(Poolable.class, "obj")
.addStatement("freeQueue.add(obj)");
@@ -682,16 +704,21 @@ public class EntityProcess extends BaseProcessor{
//add method for resizing all necessary groups
MethodSpec.Builder groupResize = MethodSpec.methodBuilder("resize")
.addParameter(TypeName.FLOAT, "x").addParameter(TypeName.FLOAT, "y").addParameter(TypeName.FLOAT, "w").addParameter(TypeName.FLOAT, "h")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder groupUpdate = MethodSpec.methodBuilder("update")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC);
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder groupPoolUpdate = MethodSpec.methodBuilder("updatePooling")
.addModifiers(Modifier.PUBLIC);
//free everything pooled at the start of each updaet
groupUpdate
groupPoolUpdate
.addStatement("for($T p : freeQueue) $T.free(p)", Poolable.class, Pools.class)
.addStatement("freeQueue.clear()");
groupUpdate.addStatement("updatePooling()");
//method resize
for(GroupDefinition group : groupDefs){
if(group.spatial){
@@ -713,6 +740,7 @@ public class EntityProcess extends BaseProcessor{
}
groupsBuilder.addMethod(groupResize.build());
groupsBuilder.addMethod(groupPoolUpdate.build());
groupsBuilder.addMethod(groupUpdate.build());
write(groupsBuilder);
@@ -988,13 +1016,13 @@ public class EntityProcess extends BaseProcessor{
class GroupDefinition{
final String name;
final ClassName baseType;
final Seq<Stype> components;
final Seq<Stype> components, excludedComponents;
final boolean spatial, mapping, collides, updates;
final ObjectSet<Selement> manualInclusions = new ObjectSet<>();
public GroupDefinition(String name, ClassName bestType, Seq<Stype> components, boolean spatial, boolean mapping, boolean collides, boolean updates){
public GroupDefinition(String name, ClassName bestType, Seq<Stype> components, Seq<Stype> excludedComponents, boolean spatial, boolean mapping, boolean collides, boolean updates){
this.baseType = bestType;
this.components = components;
this.excludedComponents = excludedComponents;
this.name = name;
this.spatial = spatial;
this.mapping = mapping;
@@ -8,6 +8,7 @@ import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import arc.util.serialization.*;
import arc.util.serialization.Jval.*;
import com.squareup.javapoet.*;
import mindustry.annotations.Annotations.*;
import mindustry.annotations.*;
@@ -36,7 +37,7 @@ public class AssetsProcess extends BaseProcessor{
MethodSpec.Builder icload = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
CodeBlock.Builder ichinit = CodeBlock.builder();
String resources = rootDirectory + "/core/assets-raw/sprites/ui";
Jval icons = Jval.read(Fi.get(rootDirectory + "/core/assets-raw/fontgen/config.json").readString());
JsonArray icons = Jval.read(Fi.get(rootDirectory + "/core/assets-raw/icons/codepoints.json").readString()).asArray();
ObjectMap<String, String> texIcons = new OrderedMap<>();
PropertiesUtils.load(texIcons, Fi.get(rootDirectory + "/core/assets/icons/icons.properties").reader());
@@ -62,10 +63,10 @@ public class AssetsProcess extends BaseProcessor{
ObjectSet<String> used = new ObjectSet<>();
for(Jval val : icons.get("glyphs").asArray()){
String name = capitalize(val.getString("css", ""));
for(Jval val : icons){
String name = capitalize(val.getString("name", ""));
if(!val.getBool("selected", true) || !used.add(name)) continue;
if(!used.add(name)) continue;
int code = val.getInt("code", 0);
iconcAll.append((char)code);
@@ -20,7 +20,7 @@ public class LoadRegionProcessor extends BaseProcessor{
.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"deprecation\"").build())
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder method = MethodSpec.methodBuilder("loadRegions")
.addParameter(tname("mindustry.ctype.MappableContent"), "content")
.addParameter(tname("mindustry.type.MappableContent"), "content")
.addModifiers(Modifier.STATIC, Modifier.PUBLIC);
ObjectMap<Stype, Seq<Svar>> fieldMap = new ObjectMap<>();
@@ -25,7 +25,7 @@ public class LogicStatementProcessor extends BaseProcessor{
MethodSpec.Builder reader = MethodSpec.methodBuilder("read")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(tname("mindustry.logic.LStatement"))
.returns(tname("mindustry.logic.LogicStatement"))
.addParameter(String[].class, "tokens")
.addParameter(int.class, "length");
@@ -35,8 +35,8 @@ public class LogicStatementProcessor extends BaseProcessor{
ParameterizedTypeName.get(
ClassName.get(Seq.class),
ParameterizedTypeName.get(ClassName.get(Prov.class),
tname("mindustry.logic.LStatement"))), "allStatements", Modifier.PUBLIC, Modifier.STATIC)
.initializer("Seq.with(" + types.toString(", ", t -> "" + t.toString() + "::new") + ")").build());
tname("mindustry.logic.LogicStatement"))), "allStatements", Modifier.PUBLIC, Modifier.STATIC)
.initializer("Seq.with(" + types.toString(", ", t -> t.toString() + "::new") + ")").build());
boolean beganWrite = false, beganRead = false;
@@ -6,6 +6,7 @@ atrax=1
beta=30
block=2
corvus=24
dummy=49
elude=45
flare=3
gamma=31
@@ -0,0 +1 @@
{fields:[{name:abilities,type:"mindustry.entities.abilities.Ability[]"},{name:aimX,type:float},{name:aimY,type:float},{name:building,type:Building},{name:controller,type:mindustry.entities.units.UnitController},{name:elevation,type:float},{name:flag,type:double},{name:health,type:float},{name:isShooting,type:boolean},{name:mineTile,type:mindustry.world.Tile},{name:mounts,type:"mindustry.entities.units.WeaponMount[]"},{name:plans,type:arc.struct.Queue<mindustry.entities.units.BuildPlan>},{name:rotation,type:float},{name:shield,type:float},{name:spawnedByCore,type:boolean},{name:stack,type:mindustry.type.ItemStack},{name:statuses,type:arc.struct.Seq<mindustry.entities.units.StatusEntry>},{name:team,type:mindustry.game.Team},{name:type,type:mindustry.type.UnitType},{name:updateBuilding,type:boolean},{name:vel,type:arc.math.geom.Vec2},{name:x,type:float},{name:y,type:float}]}
+65
View File
@@ -0,0 +1,65 @@
# Temporary Files
*~
.*.swp
.DS_STORE
robovm-build/
project.xcworkspace/
xcuserdata/
xcode/native/
.gradle/
build/
bin/
target/
obj/
out/
classes/
war/
gen/
gen-external-apklibs/
Debug/
Release/
robovm-build/
ipch/
/dist
#for now
extensions/physic/
#maven sucks
pom.xml
*.dll.mdb
*.userprefs
*.sdf
*.class
hs_err_pid*
Thumbs.db
arc-*.zip
arc-*.zip.MD5
*.iml
/.idea/
#core & extension libs/ folders that have no 3rd party dependencies in them
/backends/arc-backend-robovm/libs/
/extensions/freetype/libs/
/extensions/freetype/jni/
/extensions/freetype/Users/
/extensions/filedialogs/jni/
/extensions/filedialogs/libs/
/backends/backend-sdl/jni
/backends/backend-robovm/res/META-INF/robovm/ios/libs/
/arc-core/libs/
/arc-core/jni/
/arc-core/obj/
/arc-core/Users/
/arc-core/csrc/stb_image.h
/arc-core/csrc/soloud
/arc-core/csrc/freetype
/arc-core/csrc/freetype.tar.gz
#directories created by fetch.xml
/tmp/
#gradle wrapper
/local.properties
+202
View File
@@ -0,0 +1,202 @@
import com.badlogic.gdx.jnigen.gradle.JnigenExtension.*
import java.nio.file.*
plugins{
id("com.badlogicgames.jnigen.jnigen-gradle")
}
sourceSets{
main{
java.setSrcDirs(listOf("src"))
}
test{
java.setSrcDirs(listOf("test"))
resources.setSrcDirs(listOf("test/resources"))
}
}
val extraLibs = configurations.create("extraLibs")
dependencies{
testImplementation("junit:junit:4.11")
testImplementation(project(":natives:natives-desktop"))
testImplementation(files("unsafe/unsafe.jar"))
//file generated from UnsafeBuffers.java
compileOnly(files("unsafe/unsafe.jar"))
extraLibs(files("unsafe/unsafe.jar"))
}
tasks.jar{
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from(provider{ extraLibs.map{ if(it.isDirectory) it else zipTree(it) } })
}
//now, you may ask: why don't I make this a new module? why do I include JARs in the repository? why don't I make this a separate build step?
//the reason is: I don't want to deal with compiler arguments, --add-opens, or whatever else Java throws at you these days
//this just works and I don't want to touch it, it's a dependency that has already been compiled and won't explode as much as source compilation might
//"why are you using unsafe, why aren't you using the new memory access APIs?" because they don't work on Android or iOS
//and no, I cannot work with buffer put() because of Java's idiotic design making it so that you need to put()/limit()/position() to write memory, breaking multithreading
//this makes Unsafe the only viable option - any "state independent" methods are Java-16 specific, and iOS/Android don't support those
tasks.register<Exec>("compileBuffersUnsafe"){
workingDir = file("unsafe")
commandLine("javac --target 8 --source 8 -d . UnsafeBuffers.java".split(" "))
}
tasks.register<Exec>("compileBuffersSafe"){
workingDir = file("unsafe")
commandLine("javac --target 16 --source 16 -d . Java16Buffers.java".split(" "))
}
tasks.register<Exec>("recompileUnsafe"){
dependsOn("compileBuffersUnsafe", "compileBuffersSafe")
workingDir = file("unsafe")
commandLine("jar cvf unsafe.jar arc".split(" "))
doLast{
delete("unsafe/arc")
}
}
tasks.test{
testLogging{
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
showStandardStreams = true
}
}
jnigen{
sharedLibName = "arc"
libsDir = "build/natives"
val root = "csrc"
val fdir = "$root/freetype"
all{
headerDirs = arrayOf(
"$root/soloud/include", "$root/soloud/src/audiosource/wav", root,
"$fdir/include", "$fdir/include/freetype", "$fdir/include/freetype/config",
"$fdir/include/freetype/internal", "$fdir/include/freetype/internal/services"
)
cppIncludes = arrayOf("$root/*.cpp", "$root/soloud/src/core/**.cpp", "$root/soloud/src/audiosource/wav/**.cpp", "$root/soloud/src/audiosource/wav/**.c", "$root/soloud/src/filter/**.cpp")
cIncludes = arrayOf(
"$fdir/src/base/ftsystem.c", "$fdir/src/base/ftinit.c", "$fdir/src/base/ftdebug.c",
"$fdir/src/base/ftbase.c", "$fdir/src/base/ftbbox.c", "$fdir/src/base/ftglyph.c",
"$fdir/src/base/ftbitmap.c", "$fdir/src/base/ftstroke.c", "$fdir/src/base/ftmm.c",
"$fdir/src/truetype/truetype.c", "$fdir/src/sfnt/sfnt.c",
"$fdir/src/smooth/smooth.c",
"$fdir/src/autofit/autofit.c", "$fdir/src/gzip/ftgzip.c", "$fdir/src/psnames/psnames.c"
)
cppFlags += "-DSOLOUD_MAX_VOICE_COUNT=100"
cFlags += "-DFT2_BUILD_LIBRARY"
cppFlags += "-DFT2_BUILD_LIBRARY"
cFlags += "-flto"
cppFlags += "-flto"
linkerFlags += "-flto"
}
addLinux(x64, x86)
addLinux(x64, ARM)
each({ it.os == Linux }){
headerDirs += "$root/soloud/src/backend/miniaudio/"
cppIncludes += "$root/soloud/src/backend/miniaudio/*.cpp"
cppFlags += "-DWITH_MINIAUDIO"
libraries += "-lpthread -lrt -lm -ldl".split(" ")
}
addWindows(x64, x86){
headerDirs += "$root/soloud/src/backend/miniaudio/"
cppIncludes += "$root/soloud/src/backend/miniaudio/*.cpp"
cppFlags += arrayOf("-msse", "-DWITH_MINIAUDIO")
}
addAndroid{
linkerFlags += "-llog -lOpenSLES".split(" ")
cppIncludes += "$root/soloud/src/backend/opensles/*.cpp"
cppFlags += "-DWITH_OPENSLES"
androidApplicationMk += "APP_STL := c++_static"
}
addMac(x64, ARM)
each({ it.os == MacOsX }){
cppIncludes += "$root/soloud/src/backend/coreaudio/*.mm"
cppFlags += arrayOf("-std=c++11", "-DWITH_COREAUDIO")
libraries += "-Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox".split(" ")
}
addIOS{
headerDirs += "$root/iosgl"
cppIncludes += arrayOf("$root/soloud/src/backend/coreaudio/*.mm", "$root/iosgl/**.cpp")
cppFlags += arrayOf("-stdlib=libc++", "-std=c++11", "-DWITH_COREAUDIO")
libraries += "-Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AVFoundation -Wl,-framework,Foundation".split(" ")
linkerFlags += arrayOf("-undefined", "dynamic_lookup")
}
}
tasks.register("copyUnsafeStuff"){
doLast{
copy{
from(zipTree("unsafe/unsafe.jar"))
into("build/classes/java/main")
include("**/*.class")
}
}
}
tasks.register("cleanNatives"){
doLast{
delete("$rootDir/arc-core/csrc/soloud")
delete("$rootDir/arc-core/csrc/stb_image.h")
}
}
val soloudVersion = "2026.09.04"
fun runQuietly(vararg command: String, workingDir: File? = null){
providers.exec{
commandLine(*command)
if(workingDir != null) this.workingDir = workingDir
isIgnoreExitValue = true
}.result.get()
}
tasks.register("preJni"){
doFirst{
if(!file("csrc/stb_image.h").exists()){
println("Fetching stb_image source...")
//currently locked to a specific commit
runQuietly("curl", "-o", "$rootDir/arc-core/csrc/stb_image.h", "https://raw.githubusercontent.com/nothings/stb/013ac3beddff3dbffafd5177e7972067cd2b5083/stb_image.h")
}
if(!file("csrc/soloud").exists()){
println("Fetching soloud source...")
runQuietly("git", "clone", "--depth", "1", "--branch", soloudVersion, "https://github.com/Anuken/soloud.git", "$rootDir/arc-core/csrc/soloud")
}
val freetypeRoot = file("csrc")
val freetypeDir = file("csrc/freetype")
if(!freetypeDir.exists()){
val extractedFreetypeDir = file("csrc/freetype-2.14.3")
if(!extractedFreetypeDir.exists()){
println("Fetching freetype source...")
freetypeRoot.mkdirs()
providers.exec{
workingDir = freetypeRoot
commandLine("wget", "-c", "https://sourceforge.net/projects/freetype/files/freetype2/2.14.3/freetype-2.14.3.tar.gz/download", "-O", "freetype.tar.gz")
}.result.get()
providers.exec{
workingDir = freetypeRoot
commandLine("tar", "-xf", "freetype.tar.gz")
}.result.get()
}
Files.move(extractedFreetypeDir.toPath(), freetypeDir.toPath())
}
file("csrc/freetype/include/freetype/config/ftmodule.h").writeText(
"""
FT_USE_MODULE( FT_Module_Class, autofit_module_class )
FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
FT_USE_MODULE( FT_Module_Class, psnames_module_class )
FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
""".trimIndent() + "\n"
)
}
}
getTasksByName("jnigen", true).forEach{
it.dependsOn("copyUnsafeStuff", "preJni")
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+756
View File
@@ -0,0 +1,756 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class arc_backend_robovm_IOSGLES30 */
#ifndef _Included_arc_backend_robovm_IOSGLES30
#define _Included_arc_backend_robovm_IOSGLES30
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: init
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_init
(JNIEnv *, jclass);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glReadBuffer
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glReadBuffer
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDrawRangeElements
* Signature: (IIIIILjava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDrawRangeElements__IIIIILjava_nio_Buffer_2
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDrawRangeElements
* Signature: (IIIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDrawRangeElements__IIIIII
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glTexImage3D
* Signature: (IIIIIIIIILjava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glTexImage3D__IIIIIIIIILjava_nio_Buffer_2
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glTexImage3D
* Signature: (IIIIIIIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glTexImage3D__IIIIIIIIII
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glTexSubImage3D
* Signature: (IIIIIIIIIILjava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glTexSubImage3D__IIIIIIIIIILjava_nio_Buffer_2
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glTexSubImage3D
* Signature: (IIIIIIIIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glTexSubImage3D__IIIIIIIIIII
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glCopyTexSubImage3D
* Signature: (IIIIIIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glCopyTexSubImage3D
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenQueries
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenQueries__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenQueries
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenQueries__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteQueries
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteQueries__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteQueries
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteQueries__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glIsQuery
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_arc_backend_robovm_IOSGLES30_glIsQuery
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBeginQuery
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBeginQuery
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glEndQuery
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glEndQuery
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetQueryiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetQueryiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetQueryObjectuiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetQueryObjectuiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUnmapBuffer
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_arc_backend_robovm_IOSGLES30_glUnmapBuffer
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetBufferPointerv
* Signature: (II)Ljava/nio/Buffer;
*/
JNIEXPORT jobject JNICALL Java_arc_backend_robovm_IOSGLES30_glGetBufferPointerv
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDrawBuffers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDrawBuffers
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformMatrix2x3fv
* Signature: (IIZLjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformMatrix2x3fv
(JNIEnv *, jobject, jint, jint, jboolean, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformMatrix3x2fv
* Signature: (IIZLjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformMatrix3x2fv
(JNIEnv *, jobject, jint, jint, jboolean, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformMatrix2x4fv
* Signature: (IIZLjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformMatrix2x4fv
(JNIEnv *, jobject, jint, jint, jboolean, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformMatrix4x2fv
* Signature: (IIZLjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformMatrix4x2fv
(JNIEnv *, jobject, jint, jint, jboolean, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformMatrix3x4fv
* Signature: (IIZLjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformMatrix3x4fv
(JNIEnv *, jobject, jint, jint, jboolean, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformMatrix4x3fv
* Signature: (IIZLjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformMatrix4x3fv
(JNIEnv *, jobject, jint, jint, jboolean, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBlitFramebuffer
* Signature: (IIIIIIIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBlitFramebuffer
(JNIEnv *, jobject, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glRenderbufferStorageMultisample
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glRenderbufferStorageMultisample
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glFramebufferTextureLayer
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glFramebufferTextureLayer
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glFlushMappedBufferRange
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glFlushMappedBufferRange
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBindVertexArray
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBindVertexArray
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteVertexArrays
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteVertexArrays__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteVertexArrays
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteVertexArrays__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenVertexArrays
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenVertexArrays__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenVertexArrays
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenVertexArrays__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glIsVertexArray
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_arc_backend_robovm_IOSGLES30_glIsVertexArray
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBeginTransformFeedback
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBeginTransformFeedback
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glEndTransformFeedback
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glEndTransformFeedback
(JNIEnv *, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBindBufferRange
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBindBufferRange
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBindBufferBase
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBindBufferBase
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glTransformFeedbackVaryings
* Signature: (I[Ljava/lang/String;I)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glTransformFeedbackVaryings
(JNIEnv *, jobject, jint, jobjectArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glVertexAttribIPointer
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glVertexAttribIPointer
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetVertexAttribIiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetVertexAttribIiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetVertexAttribIuiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetVertexAttribIuiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glVertexAttribI4i
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glVertexAttribI4i
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glVertexAttribI4ui
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glVertexAttribI4ui
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetUniformuiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetUniformuiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetFragDataLocation
* Signature: (ILjava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_arc_backend_robovm_IOSGLES30_glGetFragDataLocation
(JNIEnv *, jobject, jint, jstring);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniform1uiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniform1uiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniform3uiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniform3uiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniform4uiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniform4uiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glClearBufferiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glClearBufferiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glClearBufferuiv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glClearBufferuiv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glClearBufferfv
* Signature: (IILjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glClearBufferfv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glClearBufferfi
* Signature: (IIFI)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glClearBufferfi
(JNIEnv *, jobject, jint, jint, jfloat, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetStringi
* Signature: (II)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_arc_backend_robovm_IOSGLES30_glGetStringi
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glCopyBufferSubData
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glCopyBufferSubData
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetUniformIndices
* Signature: (I[Ljava/lang/String;Ljava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetUniformIndices
(JNIEnv *, jobject, jint, jobjectArray, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetActiveUniformsiv
* Signature: (IILjava/nio/IntBuffer;ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetActiveUniformsiv
(JNIEnv *, jobject, jint, jint, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetUniformBlockIndex
* Signature: (ILjava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_arc_backend_robovm_IOSGLES30_glGetUniformBlockIndex
(JNIEnv *, jobject, jint, jstring);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetActiveUniformBlockiv
* Signature: (IIILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetActiveUniformBlockiv
(JNIEnv *, jobject, jint, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetActiveUniformBlockName
* Signature: (IILjava/nio/Buffer;Ljava/nio/Buffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetActiveUniformBlockName__IILjava_nio_Buffer_2Ljava_nio_Buffer_2
(JNIEnv *, jobject, jint, jint, jobject, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetActiveUniformBlockName
* Signature: (II)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_arc_backend_robovm_IOSGLES30_glGetActiveUniformBlockName__II
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glUniformBlockBinding
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glUniformBlockBinding
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDrawArraysInstanced
* Signature: (IIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDrawArraysInstanced
(JNIEnv *, jobject, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDrawElementsInstanced
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDrawElementsInstanced
(JNIEnv *, jobject, jint, jint, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetInteger64v
* Signature: (ILjava/nio/LongBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetInteger64v
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetBufferParameteri64v
* Signature: (IILjava/nio/LongBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetBufferParameteri64v
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenSamplers
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenSamplers__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenSamplers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenSamplers__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteSamplers
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteSamplers__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteSamplers
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteSamplers__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glIsSampler
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_arc_backend_robovm_IOSGLES30_glIsSampler
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBindSampler
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBindSampler
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glSamplerParameteri
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glSamplerParameteri
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glSamplerParameteriv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glSamplerParameteriv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glSamplerParameterf
* Signature: (IIF)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glSamplerParameterf
(JNIEnv *, jobject, jint, jint, jfloat);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glSamplerParameterfv
* Signature: (IILjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glSamplerParameterfv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetSamplerParameteriv
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetSamplerParameteriv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGetSamplerParameterfv
* Signature: (IILjava/nio/FloatBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGetSamplerParameterfv
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glVertexAttribDivisor
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glVertexAttribDivisor
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glBindTransformFeedback
* Signature: (II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glBindTransformFeedback
(JNIEnv *, jobject, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteTransformFeedbacks
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteTransformFeedbacks__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glDeleteTransformFeedbacks
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glDeleteTransformFeedbacks__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenTransformFeedbacks
* Signature: (I[II)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenTransformFeedbacks__I_3II
(JNIEnv *, jobject, jint, jintArray, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glGenTransformFeedbacks
* Signature: (ILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glGenTransformFeedbacks__ILjava_nio_IntBuffer_2
(JNIEnv *, jobject, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glIsTransformFeedback
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_arc_backend_robovm_IOSGLES30_glIsTransformFeedback
(JNIEnv *, jobject, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glPauseTransformFeedback
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glPauseTransformFeedback
(JNIEnv *, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glResumeTransformFeedback
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glResumeTransformFeedback
(JNIEnv *, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glProgramParameteri
* Signature: (III)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glProgramParameteri
(JNIEnv *, jobject, jint, jint, jint);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glInvalidateFramebuffer
* Signature: (IILjava/nio/IntBuffer;)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glInvalidateFramebuffer
(JNIEnv *, jobject, jint, jint, jobject);
/*
* Class: arc_backend_robovm_IOSGLES30
* Method: glInvalidateSubFramebuffer
* Signature: (IILjava/nio/IntBuffer;IIII)V
*/
JNIEXPORT void JNICALL Java_arc_backend_robovm_IOSGLES30_glInvalidateSubFramebuffer
(JNIEnv *, jobject, jint, jint, jobject, jint, jint, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
+148
View File
@@ -0,0 +1,148 @@
package arc;
import arc.graphics.*;
import arc.struct.*;
import arc.util.*;
import java.net.*;
public interface Application extends Disposable{
/** Returns a list of all the application listeners used. */
Seq<ApplicationListener> getListeners();
/** Adds a new application listener. */
default void addListener(ApplicationListener listener){
synchronized(getListeners()){
getListeners().add(listener);
}
}
/** Removes an application listener. */
default void removeListener(ApplicationListener listener){
post(() -> {
synchronized(getListeners()){
getListeners().remove(listener);
}
});
}
/** Call this before update() in each backend. */
default void defaultUpdate(){
Core.settings.autosave();
Time.updateGlobal();
}
/** @return what {@link ApplicationType} this application has, e.g. Android or Desktop */
ApplicationType getType();
default boolean isDesktop(){
return getType() == ApplicationType.desktop;
}
default boolean isHeadless(){
return getType() == ApplicationType.headless;
}
default boolean isAndroid(){
return getType() == ApplicationType.android;
}
default boolean isIOS(){
return getType() == ApplicationType.iOS;
}
default boolean isMobile(){
return isAndroid() || isIOS();
}
default boolean isWeb(){
return getType() == ApplicationType.web;
}
/** @return the Android API level on Android, the major OS version on iOS (5, 6, 7, ..), or 0 on the desktop. */
default int getVersion(){
return 0;
}
/** @return the Java heap memory use in bytes. */
default long getJavaHeap(){
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
/** @return the Native heap memory use in bytes. Only valid on Android. */
default long getNativeHeap(){
return 0;
}
/** @return the main graphics thread, upon which all ApplicationListener methods are called. May return null if not initialized. */
default @Nullable Thread getMainThread(){
return null;
}
/**
* @return whether the currently executing thread is the main thread.
* If the main thread is not initialized, returns true by default. This is used for error checking purposes.
* */
default boolean isOnMainThread(){
Thread thread = getMainThread();
return thread == null || Thread.currentThread() == thread;
}
@Nullable String getClipboardText();
void setClipboardText(String text);
default void setClipboardImage(Pixmap pixmap){
//no-op
}
/** Open a folder in the system's file browser.
* @return whether this operation was successful. */
default boolean openFolder(String file){
return false;
}
/**
* Launches the default browser to display a URI. If the default browser is not able to handle the specified URI, the
* application registered for handling URIs of the specified type is invoked. The application is determined from the protocol
* and path of the URI. A best effort is made to open the given URI; however, since external applications are involved, no guarantee
* can be made as to whether the URI was actually opened. If it is known that the URI was not opened, false will be returned;
* otherwise, true will be returned.
* @param URI the URI to be opened.
* @return false if it is known the uri was not opened, true otherwise.
*/
default boolean openURI(String URI){
return false;
}
default void getDnsServers(Seq<InetSocketAddress> out){}
/** Posts a runnable on the main loop thread.*/
void post(Runnable runnable);
/**
* Schedule an exit from the application. On android, this will cause a call to pause() and dispose() some time in the future,
* it will not immediately finish your application.
* On iOS this should be avoided in production as it breaks Apples guidelines.
*/
void exit();
/** Disposes of core resources. */
@Override
default void dispose(){
//flush any changes to settings upon dispose
if(Core.settings != null){
Core.settings.autosave();
}
if(Core.audio != null){
Core.audio.dispose();
}
}
/** Enumeration of possible {@link Application} types */
enum ApplicationType{
android, desktop, headless, web, iOS
}
}
+68
View File
@@ -0,0 +1,68 @@
package arc;
import arc.files.Fi;
public abstract class ApplicationCore implements ApplicationListener{
protected ApplicationListener[] modules = {};
public void add(ApplicationListener module){
//use an array instead of a seq/list, for faster iteration; modules do not get added often, so a resize each time is acceptable
ApplicationListener[] news = new ApplicationListener[modules.length + 1];
news[news.length - 1] = module;
System.arraycopy(modules, 0, news, 0, modules.length);
modules = news;
}
public abstract void setup();
@Override
public void init(){
setup();
for(ApplicationListener listener : modules){
listener.init();
}
}
@Override
public void resize(int width, int height){
for(ApplicationListener listener : modules){
listener.resize(width, height);
}
}
@Override
public void update(){
for(ApplicationListener listener : modules){
listener.update();
}
}
@Override
public void pause(){
for(ApplicationListener listener : modules){
listener.pause();
}
}
@Override
public void resume(){
for(ApplicationListener listener : modules){
listener.resume();
}
}
@Override
public void dispose(){
for(ApplicationListener listener : modules){
listener.dispose();
}
}
@Override
public void fileDropped(Fi file){
for(ApplicationListener listener : modules){
listener.fileDropped(file);
}
}
}
@@ -0,0 +1,67 @@
package arc;
import arc.files.Fi;
/**
* <p>
* An <code>ApplicationListener</code> is called when the {@link Application} is created, resumed, rendering, paused or destroyed.
* All methods are called in a thread that has the OpenGL context current. You can thus safely create and manipulate graphics
* resources.
* </p>
*
* <p>
* The <code>ApplicationListener</code> interface follows the standard Android activity life-cycle and is emulated on the desktop
* accordingly.
* </p>
* @author mzechner
*/
public interface ApplicationListener{
/**
* Called when the {@link Application} is first created.
* Only gets called if the application is created before the listener is added.
*/
default void init(){
}
/**
* Called when the {@link Application} is resized. This can happen at any point during a non-paused state but will never happen
* before a call to {@link #init()}.
* @param width the new width in pixels
* @param height the new height in pixels
*/
default void resize(int width, int height){
}
/** Called when the {@link Application} should update itself. */
default void update(){
}
/**
* Called when the {@link Application} is paused, usually when it's not active or visible on screen. An Application is also
* paused before it is destroyed.
*/
default void pause(){
}
/** Called when the {@link Application} is resumed from a paused state, usually when it regains focus. */
default void resume(){
}
/** Called when the {@link Application} is destroyed. Preceded by a call to {@link #pause()}. */
default void dispose(){
}
/**
* Called when the applications exits gracefully, either through `Core.app.exit()` or through a window closing.
* Never called after a crash, unlike dispose().
* */
default void exit(){
}
/**
* Called when an external file is dropped into the window, e.g from the desktop.
*/
default void fileDropped(Fi file){
}
}
+32
View File
@@ -0,0 +1,32 @@
package arc;
import arc.assets.*;
import arc.audio.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.gl.*;
import arc.scene.*;
import arc.util.*;
import java.util.concurrent.*;
/** Global references to all of Arc's core modules. */
public class Core{
public static Application app;
public static Graphics graphics;
public static Audio audio;
public static Input input;
public static Files files;
public static Settings settings;
public static I18NBundle bundle = I18NBundle.createEmptyBundle();
public static Camera camera;
public static Batch batch;
public static Scene scene;
public static AssetManager assets;
public static TextureAtlas atlas;
public static ExecutorService executor = Threads.executor("Main Executor", OS.cores);
/** This class should never be used directly - use {@link Gl} instead. */
public static GLProvider glProvider;
}
+62
View File
@@ -0,0 +1,62 @@
package arc;
import arc.struct.Seq;
import arc.struct.ObjectMap;
import arc.func.Cons;
/** Simple global event listener system. */
@SuppressWarnings("unchecked")
public class Events{
private static final ObjectMap<Object, Seq<Cons<?>>> events = new ObjectMap<>();
/** Handle an event by class. */
public static <T> void on(Class<T> type, Cons<T> listener){
events.get(type, () -> new Seq<>(Cons.class)).add(listener);
}
/** Handle an event by enum trigger. */
public static void run(Object type, Runnable listener){
events.get(type, () -> new Seq<>(Cons.class)).add(e -> listener.run());
}
/** Only use this method if you have the reference to the exact listener object that was used. */
public static <T> boolean remove(Class<T> type, Cons<T> listener){
return events.get(type, () -> new Seq<>(Cons.class)).remove(listener);
}
/** Fires an enum trigger. */
public static <T extends Enum<T>> void fire(Enum<T> type){
Seq<Cons<?>> listeners = events.get(type);
if(listeners != null){
int len = listeners.size;
Cons[] items = listeners.items;
for(int i = 0; i < len; i++){
items[i].get(type);
}
}
}
/** Fires a non-enum event by class. */
public static <T> void fire(T type){
fire(type.getClass(), type);
}
public static <T> void fire(Class<?> ctype, T type){
Seq<Cons<?>> listeners = events.get(ctype);
if(listeners != null){
int len = listeners.size;
Cons[] items = listeners.items;
for(int i = 0; i < len; i++){
items[i].get(type);
}
}
}
/** Don't do this. */
public static void clear(){
events.clear();
}
}
+114
View File
@@ -0,0 +1,114 @@
package arc;
import arc.audio.Audio;
import arc.files.Fi;
import arc.util.ArcRuntimeException;
/**
* Provides standard access to the filesystem, classpath, Android SD card, and Android assets directory.
* @author mzechner
* @author Nathan Sweet
*/
public interface Files{
/**
* Returns a handle representing a file or directory.
* @param type Determines how the path is resolved.
* @throws ArcRuntimeException if the type is classpath or internal and the file does not exist.
* @see FileType
*/
Fi get(String path, FileType type);
/** Convenience method that returns a {@link FileType#classpath} file handle. */
default Fi classpath(String path){
return get(path, FileType.classpath);
}
/** Convenience method that returns a {@link FileType#internal} file handle. */
default Fi internal(String path){
return get(path, FileType.internal);
}
/** Convenience method that returns a {@link FileType#external} file handle. */
default Fi external(String path){
return get(path, FileType.external);
}
/** Convenience method that returns a {@link FileType#absolute} file handle. */
default Fi absolute(String path){
return get(path, FileType.absolute);
}
/** Convenience method that returns a {@link FileType#local} file handle. */
default Fi local(String path){
return get(path, FileType.local);
}
/** Convenience method that returns a cache file handle. */
default Fi cache(String path){
return get(getCachePath(), FileType.absolute).child(path);
}
/** @return absolute path to cache directory. */
default String getCachePath(){
return local("cache").absolutePath();
}
/** @return on IOS, the internal path to the assets directory. Not used on other platforms. */
default String getInternalStoragePath(){
return "";
}
/**
* @return the external storage path directory. This is the SD card on Android and the home directory of the current user on
* the desktop.
*/
String getExternalStoragePath();
/**
* @return true if the external storage is ready for file IO. Eg, on Android, the SD card is not available when mounted for use
* with a PC.
*/
boolean isExternalStorageAvailable();
/**
* @return the local storage path directory. This is the private files directory on Android and the directory of the jar on the
* desktop.
*/
String getLocalStoragePath();
/** @return true if the local storage is ready for file IO. */
boolean isLocalStorageAvailable();
/**
* Indicates how to resolve a path to a file.
* @author mzechner
* @author Nathan Sweet
*/
enum FileType{
/**
* Path relative to the root of the classpath. Classpath files are always readonly. Note that classpath files are not
* compatible with some functionality on Android, such as {@link arc.audio.Audio#newSound(Fi)} and
* {@link Audio#newMusic(Fi)}.
*/
classpath,
/**
* Path relative to the asset directory on Android and to the application's root directory on the desktop. On the desktop,
* if the file is not found, then the classpath is checked. This enables files to be found when using JWS or applets.
* Internal files are always readonly.
*/
internal,
/** Path relative to the root of the SD card on Android and to the home directory of the current user on the desktop. */
external,
/**
* Path that is a fully qualified, absolute filesystem path. To ensure portability across platforms use absolute files only
* when absolutely (heh) necessary.
*/
absolute,
/** Path relative to the private files directory on Android and to the application's root directory on the desktop. */
local
}
}
+359
View File
@@ -0,0 +1,359 @@
package arc;
import arc.Graphics.Cursor.*;
import arc.graphics.*;
import arc.graphics.gl.*;
import arc.graphics.gl.GLVersion.*;
import arc.math.*;
import arc.util.*;
/**
* This interface encapsulates communication with the graphics processor. Depending on the available hardware and the current
* {@link Application} configuration, access to {@link GLProvider} are provided here.
* <p>
* If supported by the backend, this interface lets you query the available display modes (graphics resolution and color depth)
* and change it.
* <p>
* This interface can be used to switch between continuous and non-continuous rendering (see
* {@link #setContinuousRendering(boolean)}), and to explicitly {@link #requestRendering()}.
* <p>
* @author mzechner
*/
public abstract class Graphics implements Disposable{
/** The last cursor used. Can be Cursor or SystemCursor.*/
private Object lastCursor;
/** @return whether instancing with glVertexAttribDivisor and glDrawElementsInstanced is available on this platform. */
public boolean supportsInstancing(){
//instancing via glDrawElementsInstanced + glVertexAttribDivisor is available on GL ES 3.0; otherwise, only >= Gl 3.3 has glVertexAttribDivisor on desktop
return getGLVersion().type == GlType.GLES || getGLVersion().atLeast(3, 3);
}
/** Clears the color buffer using the specified color. */
public void clear(float r, float g, float b, float a){
Gl.clearColor(r, g, b, a);
Gl.clear(Gl.colorBufferBit);
}
/** Clears the color buffer using the specified color. */
public void clear(Color color){
clear(color.r, color.g, color.b, color.a);
}
/** Returns whether this application is probably in portrait mode, e.g. if width < height.*/
public boolean isPortrait(){
return getWidth() < getHeight();
}
/** @return the width of the client area in logical pixels. */
public abstract int getWidth();
/** @return the height of the client area in logical pixels */
public abstract int getHeight();
/** @return the aspect ratio, e.g. width/height */
public float getAspect(){
return (float)getWidth() / getHeight();
}
/** @return whether the window is 'hidden', e.g. whether width or height of the window is less than 2.
* This is due to Windows reporting window size as 0 or 1 when minimized. This causes framebuffers to crash if resized.
*/
public boolean isHidden(){
return getWidth() < 2 || getHeight() < 2;
}
/** @return the width of the framebuffer in physical pixels */
public abstract int getBackBufferWidth();
/** @return the height of the framebuffer in physical pixels */
public abstract int getBackBufferHeight();
/** @return the safe area insets, in the order left-right-top-bottom. */
public int[] getSafeInsets(){
return new int[4];
}
/**
* Returns the id of the current frame. The general contract of this method is that the id is incremented only when the
* application is in the running state right before calling the {@link ApplicationListener#update()} method. Also, the id of
* the first frame is 0; the id of subsequent frames is guaranteed to take increasing values for 2<sup>63</sup>-1 rendering
* cycles.
* @return the id of the current frame
*/
public abstract long getFrameId();
/** @return the time span between the current frame and the last frame in seconds. Might be smoothed over n frames. */
public abstract float getDeltaTime();
/** @return the average number of frames per second */
public abstract int getFramesPerSecond();
/** @return the {@link GLVersion} of this Graphics instance */
public abstract GLVersion getGLVersion();
/** @return the pixels per inch on the x-axis */
public abstract float getPpiX();
/** @return the pixels per inch on the y-axis */
public abstract float getPpiY();
/** @return the pixels per centimeter on the x-axis */
public abstract float getPpcX();
/** @return the pixels per centimeter on the y-axis. */
public abstract float getPpcY();
/**
* This is a scaling factor for the Density Independent Pixel unit, following the same conventions as
* android.util.DisplayMetrics#density, where one DIP is one pixel on an approximately 160 dpi screen. Thus on a 160dpi screen
* this density value will be 1; on a 120 dpi screen it would be .75; etc.
* @return the logical density of the Display.
*/
public abstract float getDensity();
/**
* Sets the window to full-screen mode.
* @return whether the operation succeeded.
*/
public boolean setFullscreen(boolean fullscreen){
return false;
}
/**
* Sets the window position on its current monitor.
*/
public void setWindowPosition(int x, int y){}
/**
* Sets the window size in pixels.
*/
public void setWindowSize(int width, int height){}
/**
* Sets the title of the window. Ignored on Android.
* @param title the title.
*/
public abstract void setTitle(String title);
/**
* Enable/Disable vsynching. This is a best-effort attempt which might not work on all platforms.
* @param vsync vsync enabled or not.
*/
public abstract void setVSync(boolean vsync);
/** @return the format of the color, depth and stencil buffer in a {@link BufferFormat} instance */
public abstract BufferFormat getBufferFormat();
/**
* @param extension the extension name
* @return whether the extension is supported
*/
public abstract boolean supportsExtension(String extension);
/** On iOS, sets the preferred frame rate. A value of 0 sets the maximum supported value for this device. */
public void setPreferredFPS(int fps){}
/** @return whether rendering is continuous. */
public abstract boolean isContinuousRendering();
/**
* Sets whether to render continuously. In case rendering is performed non-continuously, the following events will trigger a
* redraw:
*
* <ul>
* <li>A call to {@link #requestRendering()}</li>
* <li>Input events from the touch screen/mouse or keyboard</li>
* <li>A {@link Runnable} is posted to the rendering thread via {@link Application#post(Runnable)}. In the case
* of a multi-window app, all windows will request rendering if a runnable is posted to the application. To avoid this,
* post a runnable to the window instead. </li>
* </ul>
* <p>
* Life-cycle events will also be reported as usual, see {@link ApplicationListener}. This method can be called from any
* thread.
* @param isContinuous whether the rendering should be continuous or not.
*/
public abstract void setContinuousRendering(boolean isContinuous);
/** Requests a new frame to be rendered if the rendering mode is non-continuous. This method can be called from any thread. */
public abstract void requestRendering();
/** Whether the app is fullscreen or not */
public abstract boolean isFullscreen();
/**
* Create a new cursor represented by the {@link arc.graphics.Pixmap}. The Pixmap must be in RGBA8888 format,
* width & height must be powers-of-two greater than zero (not necessarily equal) and of a certain minimum size (32x32 is a safe bet),
* and alpha transparency must be single-bit (i.e., 0x00 or 0xFF only). This function returns a Cursor object that can be set as the
* system cursor by calling {@link #setCursor(Cursor)} .
* @param pixmap the mouse cursor image as a {@link arc.graphics.Pixmap}
* @param xHotspot the x location of the hotspot pixel within the cursor image (origin top-left corner)
* @param yHotspot the y location of the hotspot pixel within the cursor image (origin top-left corner)
* @return a cursor object that can be used by calling {@link #setCursor(Cursor)} or null if not supported
*/
public abstract Cursor newCursor(Pixmap pixmap, int xHotspot, int yHotspot);
/**
* Creates a new cursor by scaling a pixmap and adding an outline.
* @param pixmap The base pixmap. Unscaled.
* @param scaling The factor by which to scale the base pixmap.
* @param outlineColor The color of the cursor's outline.
*/
public Cursor newCursor(Pixmap pixmap, int scaling, Color outlineColor, int outlineThickness){
Pixmap out = Pixmaps.outline(pixmap, outlineColor, outlineThickness);
Pixmap out2 = Pixmaps.scale(out, scaling);
if(!Mathf.isPowerOfTwo(out2.width)){
Pixmap old = out2;
out2 = Pixmaps.resize(out2, Mathf.nextPowerOfTwo(out2.width), Mathf.nextPowerOfTwo(out2.width));
old.dispose();
}
out.dispose();
pixmap.dispose();
Cursor cur = newCursor(out2, out2.width / 2, out2.height / 2);
out2.dispose();
return cur;
}
/**
* Creates a new cursor by file name.
* @param filename the name of the cursor .png file, found in the internal file "cursors/{name}.png"
*/
public Cursor newCursor(String filename, int scale){
if(scale == 1 || OS.isAndroid || OS.isIos) return newCursor(filename);
Pixmap base = new Pixmap(Core.files.internal("cursors/" + filename + ".png"));
Pixmap result = Pixmaps.scale(base, base.width * scale, base.height * scale);
base.dispose();
Cursor cur = newCursor(result, result.width /2, result.height /2);
result.dispose();
return cur;
}
/**
* Creates a new cursor by file name.
* @param filename the name of the cursor .png file, found in the internal file "cursors/{name}.png"
*/
public Cursor newCursor(String filename){
Pixmap p = new Pixmap(Core.files.internal("cursors/" + filename + ".png"));
Cursor result = newCursor(p, p.width /2, p.height /2);
p.dispose();
return result;
}
/**
* Creates a new cursor by file name.
* @param filename the name of the cursor .png file, found in the internal file "cursors/{name}.png"
*/
public Cursor newCursor(String filename, int scaling, Color outlineColor, int outlineScaling){
return newCursor(new Pixmap(Core.files.internal("cursors/" + filename + ".png")), scaling, outlineColor, outlineScaling);
}
/**Sets the cursor to the default value, e.g. {@link SystemCursor#arrow}.*/
public void restoreCursor(){
cursor(SystemCursor.arrow);
}
/**Sets the display cursor.*/
public void cursor(Cursor cursor){
if(lastCursor == cursor) return;
if(cursor instanceof SystemCursor){
if(((SystemCursor)cursor).cursor != null){
setCursor(((SystemCursor)cursor).cursor);
}else{
setSystemCursor((SystemCursor)cursor);
}
}else{
setCursor(cursor);
}
lastCursor = cursor;
}
/**
* Only viable on desktop and web. Browsers that support cursor:url() and support the png format (the
* pixmap is converted to a data-url of type image/png) should also support custom cursors. Will set the mouse cursor image to
* the image represented by the {@link Cursor}. It is recommended to call this function in the main render thread, and maximum one time per frame.
* Internal use only!
* @param cursor the mouse cursor as a {@link Cursor}
*/
protected abstract void setCursor(Cursor cursor);
/**Sets one of the predefined {@link SystemCursor}s.
* Internal use only!*/
protected abstract void setSystemCursor(SystemCursor systemCursor);
@Override
public void dispose(){
for(SystemCursor cursor : SystemCursor.values()){
cursor.dispose();
}
}
/** Class describing the bits per pixel, depth buffer precision, stencil precision and number of MSAA samples. */
public static class BufferFormat{
/* number of bits per color channel */
public final int r, g, b, a;
/* number of bits for depth and stencil buffer */
public final int depth, stencil;
/** number of samples for multi-sample anti-aliasing (MSAA) **/
public final int samples;
/** whether coverage sampling anti-aliasing is used. in that case you have to clear the coverage buffer as well! */
public final boolean coverageSampling;
public BufferFormat(int r, int g, int b, int a, int depth, int stencil, int samples, boolean coverageSampling){
this.r = r;
this.g = g;
this.b = b;
this.a = a;
this.depth = depth;
this.stencil = stencil;
this.samples = samples;
this.coverageSampling = coverageSampling;
}
public String toString(){
return "r: " + r + ", g: " + g + ", b: " + b + ", a: " + a + ", depth: " + depth + ", stencil: " + stencil
+ ", num samples: " + samples + ", coverage sampling: " + coverageSampling;
}
}
/**
* <p>
* Represents a mouse cursor. Create a cursor via
* {@link Graphics#newCursor(Pixmap, int, int)}. To
* set the cursor use {@link Graphics#setCursor(Cursor)}.
* To use one of the system cursors, call Graphics#setSystemCursor
* </p>
**/
public interface Cursor extends arc.util.Disposable{
enum SystemCursor implements Cursor{
arrow,
ibeam,
crosshair,
hand,
horizontalResize,
verticalResize;
/** The override cursor to use when setting this cursor.*/
@Nullable Cursor cursor;
/** Sets the alias for this cursor. */
public void set(Cursor cursor){
this.cursor = cursor;
}
@Override
public void dispose(){
if(cursor != null && !(cursor instanceof SystemCursor)){
cursor.dispose();
cursor = null;
}
}
}
}
}
+391
View File
@@ -0,0 +1,391 @@
package arc;
import arc.func.*;
import arc.input.*;
import arc.input.KeyBind.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
/**
* <p>
* Interface to the input facilities. This allows polling the state of the keyboard, the touch screen and the accelerometer. On
* some backends (desktop) the touch screen is replaced by mouse input. The accelerometer is of course not available on
* all backends.
* </p>
*
* <p>
* The class also offers methods to use (and test for the presence of) other input systems like vibration, compass, on-screen
* keyboards, and cursor capture. Support for simple input dialogs is also provided.
* </p>
* @author mzechner
*/
public abstract class Input{
/** The default input device (keyboard) */
protected KeyboardDevice keyboard = new KeyboardDevice();
/** An input multiplexer to handle events. */
protected InputMultiplexer inputMultiplexer = new InputMultiplexer(keyboard);
/** List of caught keys for Android. */
protected IntSet caughtKeys = new IntSet();
/** Return Vec2 value for various functions. */
protected Vec2 mouseReturn = new Vec2();
/** Whether to use keyboard controls on Android. */
protected boolean useKeyboard;
/**Returns the unprojected mouse position (screen -> world).*/
public Vec2 mouseWorld(float x, float y){
return Core.camera.unproject(mouseReturn.set(x, y));
}
/**Returns the projected mouse position (world -> screen).*/
public Vec2 mouseScreen(float x, float y){
return Core.camera.project(mouseReturn.set(x, y));
}
/** @return the unprojected mouse position in the world.*/
public float mouseWorldX(){
return Core.camera.unproject(mouse()).x;
}
/** @return the unprojected mouse position in the world.*/
public float mouseWorldY(){
return Core.camera.unproject(mouse()).y;
}
/**Returns the unprojected mouse position in the world.*/
public Vec2 mouseWorld(){
return Core.camera.unproject(mouse());
}
/**Returns the mouse position as a Vec2.*/
public Vec2 mouse(){
return mouseReturn.set(mouseX(), mouseY());
}
public void setUseKeyboard(boolean useKeyboard){
this.useKeyboard = useKeyboard;
}
/** @return whether the keyboard should be preferred for mobile devices - used in text fields. */
public boolean useKeyboard(){
return useKeyboard;
}
/**
* @return The x coordinate of the last touch on touch screen devices and the current mouse position on desktop for the first
* pointer in screen coordinates. The screen origin is the top left corner.
*/
public abstract int mouseX();
/**
* Returns the x coordinate in screen coordinates of the given pointer. Pointers are indexed from 0 to n. The pointer id
* identifies the order in which the fingers went down on the screen, e.g. 0 is the first finger, 1 is the second and so on.
* When two fingers are touched down and the first one is lifted the second one keeps its index. If another finger is placed on
* the touch screen the first free index will be used.
* @param pointer the pointer id.
* @return the x coordinate
*/
public abstract int mouseX(int pointer);
/** @return the different between the current pointer location and the last pointer location on the x-axis. */
public abstract int deltaX();
/** @return the different between the current pointer location and the last pointer location on the x-axis. */
public abstract int deltaX(int pointer);
/**
* @return The y coordinate of the last touch on touch screen devices and the current mouse position on desktop for the first
* pointer in screen coordinates. The screen origin is the bottom left corner.
*/
public abstract int mouseY();
/**
* Returns the y coordinate in screen coordinates of the given pointer. Pointers are indexed from 0 to n. The pointer id
* identifies the order in which the fingers went down on the screen, e.g. 0 is the first finger, 1 is the second and so on.
* When two fingers are touched down and the first one is lifted the second one keeps its index. If another finger is placed on
* the touch screen the first free index will be used.
* @param pointer the pointer id.
* @return the y coordinate
*/
public abstract int mouseY(int pointer);
/** @return the different between the current pointer location and the last pointer location on the y-axis. */
public abstract int deltaY();
/** @return the different between the current pointer location and the last pointer location on the y-axis. */
public abstract int deltaY(int pointer);
/** @return whether the screen is currently touched. */
public abstract boolean isTouched();
/** @return whether a new touch down event just occurred. */
public abstract boolean justTouched();
public int getTouches(){
int sum = 0;
for(int i = 0; i < 10; i++){
if(isTouched(i)) sum ++;
}
return sum;
}
/**
* Whether the screen is currently touched by the pointer with the given index. Pointers are indexed from 0 to n. The pointer
* id identifies the order in which the fingers went down on the screen, e.g. 0 is the first finger, 1 is the second and so on.
* When two fingers are touched down and the first one is lifted the second one keeps its index. If another finger is placed on
* the touch screen the first free index will be used.
* @param pointer the pointer
* @return whether the screen is touched by the pointer
*/
public abstract boolean isTouched(int pointer);
/** @return the pressure of the first pointer */
public float getPressure(){
return getPressure(0);
}
/**
* Returns the pressure of the given pointer, where 0 is untouched. On Android it should be
* up to 1.0, but it can go above that slightly and its not consistent between devices. On iOS 1.0 is the normal touch
* and significantly more of hard touch. Check relevant manufacturer documentation for details.
* Check availability with {@link Input#isPeripheralAvailable(Peripheral)}. If not supported, returns 1.0 when touched.
* @param pointer the pointer id.
* @return the pressure
*/
public float getPressure(int pointer){
return isTouched(pointer) ? 1f : 0f;
}
/** Returns whether one of the two shift keys is currently pressed.*/
public boolean shift(){
return keyDown(KeyCode.shiftLeft) || keyDown(KeyCode.shiftRight);
}
/** Returns whether one of the two control keys is currently pressed - or, on Macs, the cmd key.*/
public boolean ctrl(){
return OS.isMac ? keyDown(KeyCode.sym) : keyDown(KeyCode.controlLeft) || keyDown(KeyCode.controlRight);
}
/** Returns whether one of the two alt keys is pressed.*/
public boolean alt(){
return keyDown(KeyCode.altLeft) || keyDown(KeyCode.altRight);
}
/** Returns whether the key is pressed. */
public boolean keyDown(KeyCode key){
return keyboard.isPressed(key);
}
/** Returns whether the key has just been pressed. */
public boolean keyTap(KeyCode key){
return keyboard.isTapped(key);
}
/** Returns whether the key has just been released. */
public boolean keyRelease(KeyCode key){
return keyboard.isReleased(key);
}
/** Returns the [-1, 1] axis value of a key. */
public float axis(KeyCode key){
return keyboard.getAxis(key);
}
/** Returns whether the keybind is pressed. */
public boolean keyDown(KeyBind key){
return key.value.key != null && keyboard.isPressed(key.value.key);
}
/** Returns whether the key has just been pressed. */
public boolean keyTap(KeyBind key){
return key.value.key != null && keyboard.isTapped(key.value.key);
}
/** Returns whether the key has just been released. */
public boolean keyRelease(KeyBind key){
return key.value.key != null && keyboard.isReleased(key.value.key);
}
/** Returns the [-1, 1] axis value of a key. */
public float axis(KeyBind key){
Axis axis = key.value;
if(axis.key != null){
return keyboard.getAxis(axis.key);
}else{
return keyboard.isPressed(axis.min) && keyboard.isPressed(axis.max) ? 0 :
keyboard.isPressed(axis.min) ? -1 : keyboard.isPressed(axis.max) ? 1 : 0;
}
}
/** Returns the [-1, 1] axis value of a key.
* In the case of keyboard-based axes, this will only return a value if one of the axes was just pressed. */
public float axisTap(KeyBind key){
Axis axis = key.value;
if(axis.key != null){
return keyboard.getAxis(axis.key);
}else{
return keyboard.isTapped(axis.min) ? -1 : keyboard.isTapped(axis.max) ? 1 : 0;
}
}
/**
* System dependent method to input a string of text. A dialog box will be created with the given title and the given text as a
* message for the user. Once the dialog has been closed the consumer be called on the rendering thread.
*/
public void getTextInput(TextInput input){
}
/** @return on mobile, whether text input is currently being fetched. Not implemented on other platforms. */
public boolean isShowingTextInput(){
return false;
}
/**
* Sets the on-screen keyboard visible if available. Only applicable on mobile.
* @param visible visible or not
*/
public void setOnscreenKeyboardVisible(boolean visible){
}
/**
* Vibrates for the given amount of time. Note that you'll need the permission
* <code> <uses-permission android:name="android.permission.VIBRATE" /></code> in your manifest file in order for this to work.
* @param milliseconds the number of milliseconds to vibrate.
*/
public void vibrate(int milliseconds){
}
/**
* Vibrate with a given pattern. Pass in an array of ints that are the times at which to turn on or off the vibrator. The first
* one is how long to wait before turning it on, and then after that it alternates. If you want to repeat, pass the index into
* the pattern at which to start the repeat.
* @param pattern an array of longs of times to turn the vibrator on or off.
* @param repeat the index into pattern at which to repeat, or -1 if you don't want to repeat.
*/
public void vibrate(long[] pattern, int repeat){
}
/** Stops the vibrator */
public void cancelVibrate(){
}
/** @return The acceleration force in m/s^2 applied to the device, including the force of gravity */
public Vec3 getAccelerometer(){
return Vec3.Zero;
}
/** @return The rate of rotation in rad/s. */
public Vec3 getGyroscope(){
return Vec3.Zero;
}
/** @return the device's orientation in degrees in the format (pitch, roll, azimuth) corresponding to x,y,z. */
public Vec3 getOrientation(){
return Vec3.Zero;
}
/**
* Returns the rotation matrix describing the devices rotation as per <a href=
* "http://developer.android.com/reference/android/hardware/SensorManager.html#getRotationMatrix(float[], float[], float[], float[])"
* >SensorManager#getRotationMatrix(float[], float[], float[], float[])</a>. Does not manipulate the matrix if the platform
* does not have an accelerometer.
*/
public void getRotationMatrix(float[] matrix){
}
/** @return the time of the event currently reported to the {@link InputProcessor}. */
public abstract long getCurrentEventTime();
/**
* Sets whether the specified button on Android should be caught. This will prevent the app from processing the key. Will have no effect
* on the desktop.
* @param c whether to catch the button
*/
public void setCatch(KeyCode code, boolean c){
if(c){
caughtKeys.add(code.ordinal());
}else{
caughtKeys.remove(code.ordinal());
}
}
/** @return whether the back button is currently being caught */
public boolean isCatch(KeyCode code){
return caughtKeys.contains(code.ordinal());
}
/**
* Adds a {@link InputProcessor} that will receive all touch and key input events. It will be called before the
* {@link ApplicationListener#update()} method each frame.
* @param processor the InputProcessor
* */
public void addProcessor(InputProcessor processor){
inputMultiplexer.addProcessor(processor);
}
/**Removes a {@link InputProcessor} from the chain.*/
public void removeProcessor(InputProcessor processor){
inputMultiplexer.removeProcessor(processor);
}
/** @return the currently set {@link InputProcessor} or null. */
public Seq<InputProcessor> getInputProcessors(){
return inputMultiplexer.getProcessors();
}
public InputMultiplexer getInputMultiplexer(){
return inputMultiplexer;
}
/** Returns the default input device (keyboard). */
public KeyboardDevice getKeyboard(){
return keyboard;
}
/**
* Queries whether a {@link Peripheral} is currently available. In case of Android and the {@link Peripheral#hardwareKeyboard}
* this returns the whether the keyboard is currently slid out or not.
* @param peripheral the {@link Peripheral}
* @return whether the peripheral is available or not.
*/
public boolean isPeripheralAvailable(Peripheral peripheral){
return peripheral == Peripheral.hardwareKeyboard;
}
/** @return the rotation of the device with respect to its native orientation. */
public int getRotation(){
return 0;
}
/** @return the native orientation of the device. */
public Orientation getNativeOrientation(){
return Orientation.landscape;
}
/** Internal method for looking up a key's name based on keyboard layout. Internal use only - use {@link KeyCode#getName()} instead. */
public String getKeyName(KeyCode code){
return code.value;
}
public enum Orientation{
landscape, portrait
}
/** Enumeration of potentially available peripherals. Use with {@link Input#isPeripheralAvailable(Peripheral)}. */
public enum Peripheral{
hardwareKeyboard, onscreenKeyboard, multitouchScreen, accelerometer, compass, vibrator, gyroscope, rotationVector, pressure
}
/** Parameters for text input. */
public static class TextInput{
public boolean multiline = false;
public boolean allowEmpty = true;
public String title = "";
public String text = "";
public String message = "";
public boolean numeric;
public Cons<String> accepted = s -> { };
public Runnable canceled = () -> { };
public int maxLength = -1;
}
}
+463
View File
@@ -0,0 +1,463 @@
package arc;
import arc.files.*;
import arc.func.*;
import arc.struct.*;
import arc.struct.ObjectMap.*;
import arc.util.*;
import arc.util.io.*;
import arc.util.serialization.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.zip.*;
public class Settings{
protected final static byte typeBool = 0, typeInt = 1, typeLong = 2, typeFloat = 3, typeString = 4, typeBinary = 5;
protected final static int maxBackups = 10, minBackupIntervalMs = 1000 * 60 * 2;
//general state data
protected Fi dataDirectory;
protected String appName = "app";
protected ObjectMap<String, Object> defaults = new ObjectMap<>();
protected HashMap<String, Object> values = new HashMap<>();
protected boolean modified;
protected Cons<Throwable> errorHandler;
protected boolean hasErrored;
protected boolean shouldAutosave = true;
protected boolean loaded = false;
protected boolean writeCompressed = false;
private long lastBackupTime;
protected ExecutorService executor = Threads.executor("Settings Backup", 1);
//IO utility objects
protected ByteArrayOutputStream byteStream = new ByteArrayOutputStream(32);
protected ReusableByteInStream byteInputStream = new ReusableByteInStream();
protected Json json = new Json();
public void setJson(Json json){
this.json = json;
}
public void setCompressed(boolean compressed){
this.writeCompressed = compressed;
}
public String getAppName(){
return appName;
}
public void setAppName(String name){
appName = name;
}
/**Sets the error handler function.
* This function gets called when {@link #forceSave} or {@link #load} fails. This can occur most often on browsers,
* where extensions can block writing to local storage.*/
public void setErrorHandler(Cons<Throwable> handler){
errorHandler = handler;
}
/** Set whether the data should autosave immediately upon changing a value.
* Default value: true. */
public void setAutosave(boolean autosave){
this.shouldAutosave = autosave;
}
public boolean modified(){
return modified;
}
/** Loads all values and keybinds. */
public synchronized void load(){
try{
loadValues();
}catch(Throwable error){
Log.err("Error loading settings", error);
if(errorHandler != null){
if(!hasErrored) errorHandler.get(error);
}else{
throw error;
}
hasErrored = true;
}
//if loading failed, it still counts
loaded = true;
}
/** Saves all values and keybinds. */
public synchronized void forceSave(){
//never loaded, nothing to save
if(!loaded) return;
try{
saveValues();
}catch(Throwable error){
Log.err("Error writing settings", error);
if(errorHandler != null){
if(!hasErrored) errorHandler.get(error);
}else{
throw error;
}
hasErrored = true;
}
modified = false;
}
/** Manually save, if the settings have been loaded at some point. */
public synchronized void manualSave(){
if(loaded){
forceSave();
}
}
/** Saves if any modifications were done. */
public synchronized void autosave(){
if(modified && shouldAutosave){
forceSave();
modified = false;
}
}
/** Loads a settings file into {@link #values} using the specified appName. */
public synchronized void loadValues(){
//don't load settings files if neither of them exist
if(!getSettingsFile().exists() && !getBackupSettingsFile().exists()){
return;
}
try{
loadValues(getSettingsFile());
//back up the save file, as the values have now been loaded successfully
getSettingsFile().copyTo(getBackupSettingsFile());
}catch(Throwable e){
Log.err("Failed to load base settings file, attempting to load backup.", e);
Seq<Fi> attempts = getBackupFolder().seq().add(getBackupSettingsFile());
//sort with latest modified file first
attempts.sort(Structs.comparingLong(f -> -f.lastModified()));
for(Fi attempt : attempts){
try{
loadValues(attempt);
attempt.copyTo(getSettingsFile());
Log.info("Loaded backup settings file successfully!");
//break out of loop, we're done here
return;
}catch(Throwable e3){
Log.err("Failed to load backup settings file.", e3);
}
}
}
}
public synchronized void loadValues(Fi file) throws IOException{
//read the first few bytes to check if it is compressed.
byte[] header = new byte[2];
file.readBytes(header, 0, 2);
boolean compressed = header[0] == (byte)0x78 && (header[1] == (byte)0x01 || header[1] == (byte)0x5E || header[1] == (byte)0x9c || header[1] == (byte)0xda);
try(DataInputStream stream = new DataInputStream(compressed ? new InflaterInputStream(file.read(8192)) : file.read(8192))){
int amount = stream.readInt();
//current theory: when corruptions happen, the only things written to the stream are a bunch of zeroes
//try to anticipate this case and throw an exception when 0 values are written
if(amount <= 0) throw new IOException("0 values are not allowed.");
for(int i = 0; i < amount; i++){
String key = stream.readUTF();
byte type = stream.readByte();
switch(type){
case typeBool:
values.put(key, stream.readBoolean());
break;
case typeInt:
values.put(key, stream.readInt());
break;
case typeLong:
values.put(key, stream.readLong());
break;
case typeFloat:
values.put(key, stream.readFloat());
break;
case typeString:
values.put(key, stream.readUTF());
break;
case typeBinary:
int length = stream.readInt();
byte[] bytes = new byte[length];
stream.readFully(bytes);
values.put(key, bytes);
break;
default:
throw new IOException("Unknown key type: " + type);
}
}
//make sure all data was read - this helps with potential corruption
int end = stream.read();
if(end != -1){
throw new IOException("Trailing settings data; expected EOF, but got: " + end);
}
}
}
/** Saves all entries from {@link #values} into the correct location. */
public synchronized void saveValues(){
Fi file = getSettingsFile();
try(DataOutputStream stream = new DataOutputStream(writeCompressed ? new FastDeflaterOutputStream(file.write(false, 8192)) : file.write(false, 8192))){
stream.writeInt(values.size());
for(Map.Entry<String, Object> entry : values.entrySet()){
stream.writeUTF(entry.getKey());
Object value = entry.getValue();
if(value instanceof Boolean){
stream.writeByte(typeBool);
stream.writeBoolean((Boolean)value);
}else if(value instanceof Integer){
stream.writeByte(typeInt);
stream.writeInt((Integer)value);
}else if(value instanceof Long){
stream.writeByte(typeLong);
stream.writeLong((Long)value);
}else if(value instanceof Float){
stream.writeByte(typeFloat);
stream.writeFloat((Float)value);
}else if(value instanceof String){
stream.writeByte(typeString);
stream.writeUTF((String)value);
}else if(value instanceof byte[]){
stream.writeByte(typeBinary);
stream.writeInt(((byte[])value).length);
stream.write((byte[])value);
}
}
}catch(Throwable e){
//file is now corrupt, delete it
file.delete();
throw new RuntimeException("Error writing preferences: " + file, e);
}
if(Time.timeSinceMillis(lastBackupTime) > minBackupIntervalMs){
lastBackupTime = Time.millis();
executor.submit(() -> {
//make sure two backups can't happen at once.
synchronized(this){
Fi backupFolder = getBackupFolder();
Seq<Fi> previous = backupFolder.seq();
//make sure first file is most recent, last is oldest
previous.sort(Structs.comparingLong(f -> -f.lastModified()));
//create new entry in the backup folder
file.copyTo(backupFolder.child(System.currentTimeMillis() + ".bin"));
//delete older backups if they exceed the max backup count
while(previous.size >= maxBackups){
previous.pop().delete();
}
}
});
}
}
/** Returns the file used for writing settings to. Not available on all platforms! */
public Fi getSettingsFile(){
return getDataDirectory().child("settings.bin");
}
public Fi getBackupFolder(){
return getDataDirectory().child("settings_backups");
}
public Fi getBackupSettingsFile(){
return getDataDirectory().child("settings_backup.bin");
}
/** Returns the directory where all settings and data is placed. */
public Fi getDataDirectory(){
return dataDirectory == null ? Core.files.absolute(OS.getAppDataDirectoryString(appName)) : dataDirectory;
}
/** Sets the settings file where everything is written to. */
public void setDataDirectory(Fi file){
this.dataDirectory = file;
}
/**
* Set up a list of defaults values.
* Format: name1, default1, name2, default2, etc
*/
public synchronized void defaults(Object... objects){
for(int i = 0; i < objects.length; i += 2){
defaults.put((String)objects[i], objects[i + 1]);
}
}
/** Clears all preference values. */
public synchronized void clear(){
values.clear();
}
public synchronized Object getDefault(String name){
return defaults.get(name);
}
public synchronized boolean has(String name){
return values.containsKey(name);
}
public synchronized Object get(String name, Object def){
return values.containsKey(name) ? values.get(name) : def;
}
public boolean isModified(){
return modified;
}
public synchronized void putJson(String name, Object value){
putJson(name, null, value);
}
public synchronized void putJson(String name, Class<?> elementType, Object value){
byteStream.reset();
json.toUBJson(value, value == null ? null : value.getClass(), elementType, byteStream);
put(name, byteStream.toByteArray());
modified = true;
}
public synchronized <T> T getJson(String name, Class<T> type, Class elementType, Prov<T> def){
try{
if(!has(name)) return def.get();
byteInputStream.setBytes(getBytes(name));
return json.readValue(type, elementType, UBJson.read(byteInputStream));
}catch(Throwable e){
Log.err("Error reading JSON with key '" + name + "'", e);
return def.get();
}
}
public <T> T getJson(String name, Class<T> type, Prov<T> def){
return getJson(name, type, null, def);
}
public float getFloat(String name, float def){
return (float)get(name, def);
}
public long getLong(String name, long def){
return (long)get(name, def);
}
public Long getLong(String name){
return getLong(name, 0);
}
public int getInt(String name, int def){
return (int)get(name, def);
}
public boolean getBool(String name, boolean def){
Object val = get(name, def);
return val instanceof Boolean ? (Boolean)val : def;
}
public byte[] getBytes(String name, byte[] def){
return (byte[])get(name, def);
}
public String getString(String name, String def){
return (String)get(name, def);
}
public float getFloat(String name){
return getFloat(name, (float)defaults.get(name, 0f));
}
public int getInt(String name){
return getInt(name, (int)defaults.get(name, 0));
}
public boolean getBool(String name){
return getBool(name, (boolean)defaults.get(name, false));
}
/** Runs the specified code once, and never again. */
public void getBoolOnce(String name, Runnable run){
if(!getBool(name, false)){
run.run();
put(name, true);
}
}
/** Returns true once, and never again. */
public boolean getBoolOnce(String name){
boolean val = getBool(name, false);
put(name, true);
return !val;
}
public byte[] getBytes(String name){
return getBytes(name, (byte[])defaults.get(name));
}
public String getString(String name){
return getString(name, (String)defaults.get(name));
}
public void putAll(ObjectMap<String, Object> map){
for(Entry<String, Object> entry : map.entries()){
put(entry.key, entry.value);
}
}
/** Toggles a boolean value. */
public void toggle(String name){
put(name, !getBool(name));
}
/** JS compatibility method. */
public void putInt(String name, int value){
put(name, value);
}
/** JS compatibility method. */
public void putFloat(String name, float value){
put(name, value);
}
/** Stores an object in the preference map. */
public synchronized void put(String name, Object object){
if(object instanceof Float || object instanceof Integer || object instanceof Boolean || object instanceof Long
|| object instanceof String || object instanceof byte[]){
values.put(name, object);
modified = true;
}else{
throw new IllegalArgumentException("Invalid object stored: " + (object == null ? null : object.getClass()) + ".");
}
}
public synchronized void remove(String name){
values.remove(name);
modified = true;
}
public synchronized Iterable<String> keys(){
return values.keySet();
}
public synchronized int keySize(){
return values.size();
}
}
@@ -0,0 +1,56 @@
package arc.assets;
import arc.files.*;
import arc.func.*;
import arc.util.*;
/**
* Describes an asset to be loaded by its filename, type and {@link AssetLoaderParameters}. Instances of this are used in
* {@link AssetLoadingTask} to load the actual asset.
* @author mzechner
*/
public class AssetDescriptor<T>{
public final String fileName;
public final Class<T> type;
public final AssetLoaderParameters params;
/** The resolved file. May be null if the fileName has not been resolved yet. */
public Fi file;
/** Callback for when this asset is loaded.*/
public Cons<T> loaded = t -> {};
/** Callback for when this asset has an error.*/
public @Nullable Cons<Throwable> errored = null;
public AssetDescriptor(Class<T> assetType){
this(assetType.getSimpleName(), assetType, null);
}
public AssetDescriptor(String fileName, Class<T> assetType){
this(fileName, assetType, null);
}
/** Creates an AssetDescriptor with an already resolved name. */
public AssetDescriptor(Fi file, Class<T> assetType){
this(file, assetType, null);
}
public AssetDescriptor(String fileName, Class<T> assetType, AssetLoaderParameters<T> params){
this.fileName = fileName.replaceAll("\\\\", "/");
this.type = assetType;
this.params = params;
}
/** Creates an AssetDescriptor with an already resolved name. */
public AssetDescriptor(Fi file, Class<T> assetType, AssetLoaderParameters<T> params){
this.fileName = file.path().replaceAll("\\\\", "/");
this.file = file;
this.type = assetType;
this.params = params;
}
@Override
public String toString(){
return fileName +
", " +
type.getName();
}
}
@@ -0,0 +1,5 @@
package arc.assets;
public interface AssetErrorListener{
void error(AssetDescriptor asset, Throwable throwable);
}
@@ -0,0 +1,21 @@
package arc.assets;
public class AssetLoaderParameters<T>{
public LoadedCallback loadedCallback;
public AssetLoaderParameters(){
}
public AssetLoaderParameters(LoadedCallback loadedCallback){
this.loadedCallback = loadedCallback;
}
/**
* Callback interface that will be invoked when the {@link AssetManager} loaded an asset.
* @author mzechner
*/
public interface LoadedCallback{
void finishedLoading(AssetManager assetManager, String fileName, Class type);
}
}
@@ -0,0 +1,152 @@
package arc.assets;
import arc.assets.loaders.AssetLoader;
import arc.assets.loaders.AsynchronousAssetLoader;
import arc.assets.loaders.SynchronousAssetLoader;
import arc.struct.Seq;
import arc.files.Fi;
import arc.util.*;
import java.util.concurrent.*;
/**
* Responsible for loading an asset through an {@link AssetLoader} based on an {@link AssetDescriptor}.
* @author mzechner
*/
@SuppressWarnings("unchecked")
class AssetLoadingTask implements Callable<Void>{
final AssetDescriptor assetDesc;
final AssetLoader loader;
final ExecutorService executor;
final long startTime;
AssetManager manager;
volatile boolean asyncDone = false;
volatile boolean dependenciesLoaded = false;
volatile Seq<AssetDescriptor> dependencies;
volatile Future<Void> depsFuture = null;
volatile Future<Void> loadFuture = null;
volatile Object asset = null;
int ticks = 0;
volatile boolean cancel = false;
public AssetLoadingTask(AssetManager manager, AssetDescriptor assetDesc, AssetLoader loader, ExecutorService threadPool){
this.manager = manager;
this.assetDesc = assetDesc;
this.loader = loader;
this.executor = threadPool;
startTime = Time.nanos();
}
/** Loads parts of the asset asynchronously if the loader is an {@link AsynchronousAssetLoader}. */
@Override
public Void call(){
AsynchronousAssetLoader asyncLoader = (AsynchronousAssetLoader)loader;
if(!dependenciesLoaded){
dependencies = asyncLoader.getDependencies(assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
if(dependencies != null){
removeDuplicates(dependencies);
manager.injectDependencies(assetDesc.fileName, dependencies);
}else{
// if we have no dependencies, we load the async part of the task immediately.
asyncLoader.loadAsync(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
asyncDone = true;
}
}else{
asyncLoader.loadAsync(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
}
return null;
}
/**
* Updates the loading of the asset. In case the asset is loaded with an {@link AsynchronousAssetLoader}, the loaders
* {@link AsynchronousAssetLoader#loadAsync(AssetManager, String, Fi, AssetLoaderParameters)} method is first called on
* a worker thread. Once this method returns, the rest of the asset is loaded on the rendering thread via
* {@link AsynchronousAssetLoader#loadSync(AssetManager, String, Fi, AssetLoaderParameters)}.
* @return true in case the asset was fully loaded, false otherwise
*/
public boolean update(){
ticks++;
if(loader instanceof SynchronousAssetLoader){
handleSyncLoader();
}else{
handleAsyncLoader();
}
return asset != null;
}
private void handleSyncLoader(){
SynchronousAssetLoader syncLoader = (SynchronousAssetLoader)loader;
if(!dependenciesLoaded){
dependenciesLoaded = true;
dependencies = syncLoader.getDependencies(assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
if(dependencies == null){
asset = syncLoader.load(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
return;
}
removeDuplicates(dependencies);
manager.injectDependencies(assetDesc.fileName, dependencies);
}else{
asset = syncLoader.load(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
}
}
private void handleAsyncLoader(){
AsynchronousAssetLoader asyncLoader = (AsynchronousAssetLoader)loader;
if(!dependenciesLoaded){
if(depsFuture == null){
depsFuture = executor.submit(this);
}else{
if(depsFuture.isDone()){
try{
depsFuture.get();
}catch(Exception e){
throw new ArcRuntimeException("Couldn't load dependencies of asset: " + assetDesc.fileName, e);
}
dependenciesLoaded = true;
if(asyncDone){
asset = asyncLoader.loadSync(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
}
}
}
}else{
if(loadFuture == null && !asyncDone){
loadFuture = executor.submit(this);
}else{
if(asyncDone){
asset = asyncLoader.loadSync(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
}else if(loadFuture.isDone()){
try{
loadFuture.get();
}catch(Exception e){
throw new ArcRuntimeException("Couldn't load asset: " + assetDesc.fileName, e);
}
asset = asyncLoader.loadSync(manager, assetDesc.fileName, resolve(loader, assetDesc), assetDesc.params);
}
}
}
}
private Fi resolve(AssetLoader loader, AssetDescriptor assetDesc){
if(assetDesc.file == null) assetDesc.file = loader.resolve(assetDesc.fileName);
return assetDesc.file;
}
public Object getAsset(){
return asset;
}
private void removeDuplicates(Seq<AssetDescriptor> array){
boolean ordered = array.ordered;
array.ordered = true;
for(int i = 0; i < array.size; ++i){
final String fn = array.get(i).fileName;
final Class type = array.get(i).type;
for(int j = array.size - 1; j > i; --j){
if(type == array.get(j).type && fn.equals(array.get(j).fileName))
array.remove(j);
}
}
array.ordered = ordered;
}
}
@@ -0,0 +1,877 @@
package arc.assets;
import arc.*;
import arc.assets.loaders.*;
import arc.audio.*;
import arc.files.*;
import arc.graphics.*;
import arc.graphics.font.*;
import arc.graphics.g2d.*;
import arc.struct.*;
import arc.struct.ObjectMap.*;
import arc.util.*;
import java.util.concurrent.*;
/**
* Loads and stores assets like textures, bitmapfonts, tile maps, sounds, music and so on.
* @author mzechner
*/
@SuppressWarnings("unchecked")
public class AssetManager implements Disposable{
final ObjectMap<Class, ObjectMap<String, RefCountedContainer>> assets = new ObjectMap<>();
final ObjectMap<String, Class> assetTypes = new ObjectMap<>();
final ObjectMap<String, Seq<String>> assetDependencies = new ObjectMap<>();
final ObjectSet<String> injected = new ObjectSet<>();
final ObjectMap<Class, ObjectMap<String, AssetLoader>> loaders = new ObjectMap<>();
final Seq<AssetDescriptor> loadQueue = new Seq<>();
final ExecutorService executor;
final Seq<AssetLoadingTask> tasks = new Seq<>();
final FileHandleResolver resolver;
AssetErrorListener listener = null;
int loaded = 0;
int toLoad = 0;
int peakTasks = 0;
/** Creates a new AssetManager with all default loaders. */
public AssetManager(){
this(Core.files::internal);
}
/** Creates a new AssetManager with all default loaders. */
public AssetManager(FileHandleResolver resolver){
this(resolver, true);
}
/**
* Creates a new AssetManager with optionally all default loaders. If you don't add the default loaders then you do have to
* manually add the loaders you need, including any loaders they might depend on.
* @param defaultLoaders whether to add the default loaders
*/
public AssetManager(FileHandleResolver resolver, boolean defaultLoaders){
this.resolver = resolver;
if(defaultLoaders){
setLoader(Font.class, new FontLoader(resolver));
setLoader(Music.class, new MusicLoader(resolver));
setLoader(Pixmap.class, new PixmapLoader(resolver));
setLoader(Sound.class, new SoundLoader(resolver));
setLoader(TextureAtlas.class, new TextureAtlasLoader(resolver));
setLoader(Texture.class, new TextureLoader(resolver));
setLoader(I18NBundle.class, new I18NBundleLoader(resolver));
setLoader(Shader.class, new ShaderProgramLoader(resolver));
setLoader(Cubemap.class, new CubemapLoader(resolver));
}
executor = Threads.executor("Assets", 1);
}
/**
* Returns the {@link FileHandleResolver} for which this AssetManager was loaded with.
* @return the file handle resolver which this AssetManager uses
*/
public FileHandleResolver getFileHandleResolver(){
return resolver;
}
/**
* @param fileName the asset file name
* @return the asset
*/
public synchronized <T> T get(String fileName){
Class<T> type = assetTypes.get(fileName);
if(type == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
if(assetsByType == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
RefCountedContainer assetContainer = assetsByType.get(fileName);
if(assetContainer == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
T asset = (T)assetContainer.object;
if(asset == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
return asset;
}
/**
* @param fileName the asset file name
* @param type the asset type
* @return the asset
*/
public synchronized <T> T get(String fileName, Class<T> type){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
if(assetsByType == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
RefCountedContainer assetContainer = assetsByType.get(fileName);
if(assetContainer == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
T asset = (T)assetContainer.object;
if(asset == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
return asset;
}
/**
* @param fileName the asset file name
* @param type the asset type
* @return the asset, or null if not found
*/
public synchronized <T> T getOrNull(String fileName, Class<T> type){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
if(assetsByType == null) return null;
RefCountedContainer assetContainer = assetsByType.get(fileName);
if(assetContainer == null) return null;
return (T)assetContainer.object;
}
/**
* @param type the asset type
* @return all the assets matching the specified type
*/
public synchronized <T> Seq<T> getAll(Class<T> type, Seq<T> out){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
if(assetsByType != null){
for(ObjectMap.Entry<String, RefCountedContainer> asset : assetsByType.entries()){
out.add((T)asset.value.object);
}
}
return out;
}
/**
* @param type the asset type
* @return all the assets matching the specified type as entries by file name
*/
public synchronized <T> Seq<Entry<String, T>> getAllEntries(Class<T> type, Seq<Entry<String, T>> out){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
if(assetsByType != null){
for(ObjectMap.Entry<String, RefCountedContainer> asset : assetsByType.entries()){
Entry<String, T> entry = new Entry<>();
entry.key = asset.key;
entry.value = (T)asset.value.object;
out.add(entry);
}
}
return out;
}
/**
* @param assetDescriptor the asset descriptor
* @return the asset
*/
public synchronized <T> T get(AssetDescriptor<T> assetDescriptor){
return get(assetDescriptor.fileName, assetDescriptor.type);
}
/** Returns true if an asset with the specified name is loading, queued to be loaded, or has been loaded. */
public synchronized boolean contains(String fileName){
if(tasks.size > 0 && tasks.first().assetDesc.fileName.equals(fileName)) return true;
for(int i = 0; i < loadQueue.size; i++)
if(loadQueue.get(i).fileName.equals(fileName)) return true;
return isLoaded(fileName);
}
/** Returns true if an asset with the specified name and type is loading, queued to be loaded, or has been loaded. */
public synchronized boolean contains(String fileName, Class type){
if(tasks.size > 0){
AssetDescriptor assetDesc = tasks.first().assetDesc;
if(assetDesc.type == type && assetDesc.fileName.equals(fileName)) return true;
}
for(int i = 0; i < loadQueue.size; i++){
AssetDescriptor assetDesc = loadQueue.get(i);
if(assetDesc.type == type && assetDesc.fileName.equals(fileName)) return true;
}
return isLoaded(fileName, type);
}
/**
* Removes the asset and all its dependencies, if they are not used by other assets.
* @param fileName the file name
*/
public synchronized void unload(String fileName){
// check if it's currently processed (and the first element in the stack, thus not a dependency) and cancel if necessary
if(tasks.size > 0){
AssetLoadingTask currAsset = tasks.first();
if(currAsset.assetDesc.fileName.equals(fileName)){
currAsset.cancel = true;
return;
}
}
// check if it's in the queue
int foundIndex = -1;
for(int i = 0; i < loadQueue.size; i++){
if(loadQueue.get(i).fileName.equals(fileName)){
foundIndex = i;
break;
}
}
if(foundIndex != -1){
toLoad--;
loadQueue.remove(foundIndex);
return;
}
// get the asset and its type
Class type = assetTypes.get(fileName);
if(type == null) return;
RefCountedContainer assetRef = assets.get(type).get(fileName);
if(assetRef == null) return;
// if it is reference counted, decrement ref count and check if we can really get rid of it.
assetRef.count--;
if(assetRef.count <= 0){
// if it is disposable dispose it
if(assetRef.object instanceof Disposable)
((Disposable)assetRef.object).dispose();
// remove the asset from the manager.
assetTypes.remove(fileName);
assets.get(type).remove(fileName);
}
// remove any dependencies (or just decrement their ref count).
Seq<String> dependencies = assetDependencies.get(fileName);
if(dependencies != null){
for(String dependency : dependencies){
if(isLoaded(dependency)) unload(dependency);
}
}
// remove dependencies if ref count < 0
if(assetRef.count <= 0){
assetDependencies.remove(fileName);
}
}
/**
* @param asset the asset
* @return whether the asset is contained in this manager
*/
public synchronized <T> boolean containsAsset(T asset){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(asset.getClass());
if(assetsByType == null) return false;
for(String fileName : assetsByType.keys()){
T otherAsset = (T)assetsByType.get(fileName).object;
if(otherAsset == asset || asset.equals(otherAsset)) return true;
}
return false;
}
/**
* @param asset the asset
* @return the filename of the asset or null
*/
public synchronized <T> String getAssetFileName(T asset){
for(Class assetType : assets.keys()){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(assetType);
for(String fileName : assetsByType.keys()){
T otherAsset = (T)assetsByType.get(fileName).object;
if(otherAsset == asset || asset.equals(otherAsset)) return fileName;
}
}
return null;
}
/**
* @param assetDesc the AssetDescriptor of the asset
* @return whether the asset is loaded
*/
public synchronized boolean isLoaded(AssetDescriptor assetDesc){
return isLoaded(assetDesc.fileName);
}
/**
* @param fileName the file name of the asset
* @return whether the asset is loaded
*/
public synchronized boolean isLoaded(String fileName){
if(fileName == null) return false;
return assetTypes.containsKey(fileName);
}
/**
* @param fileName the file name of the asset
* @return whether the asset is loaded
*/
public synchronized boolean isLoaded(String fileName, Class type){
ObjectMap<String, RefCountedContainer> assetsByType = assets.get(type);
if(assetsByType == null) return false;
RefCountedContainer assetContainer = assetsByType.get(fileName);
if(assetContainer == null) return false;
return assetContainer.object != null;
}
/**
* Returns the default loader for the given type
* @param type The type of the loader to get
* @return The loader capable of loading the type, or null if none exists
*/
public <T> AssetLoader getLoader(final Class<T> type){
return getLoader(type, null);
}
/**
* Returns the loader for the given type and the specified filename. If no loader exists for the specific filename, the
* default loader for that type is returned.
* @param type The type of the loader to get
* @param fileName The filename of the asset to get a loader for, or null to get the default loader
* @return The loader capable of loading the type and filename, or null if none exists
*/
public <T> AssetLoader getLoader(final Class<T> type, final String fileName){
final ObjectMap<String, AssetLoader> loaders = this.loaders.get(type);
if(loaders == null || loaders.size < 1) return null;
if(fileName == null) return loaders.get("");
AssetLoader result = null;
int l = -1;
for(ObjectMap.Entry<String, AssetLoader> entry : loaders.entries()){
if(entry.key.length() > l && fileName.endsWith(entry.key)){
result = entry.value;
l = entry.key.length();
}
}
return result;
}
/**
* Adds the given asset to the loading queue of the AssetManager.
* @param fileName the file name (interpretation depends on {@link AssetLoader})
* @param type the type of the asset.
*/
public synchronized <T> AssetDescriptor<T> load(String fileName, Class<T> type){
return load(fileName, type, null);
}
/**
* Loads a custom one-time 'asset' that knows how to load itself.
*/
public synchronized AssetDescriptor loadRun(String name, Class<?> type, Runnable loadasync){
return loadRun(name, type, loadasync, () -> {});
}
/**
* Loads a custom one-time 'asset' that knows how to load itself.
*/
public synchronized AssetDescriptor loadRun(String name, Class<?> type, Runnable loadasync, Runnable loadsync){
if(getLoader(type) == null){
setLoader(type, new CustomLoader(){
@Override
public void loadAsync(AssetManager manager, String fileName, Fi file, AssetLoaderParameters parameter){
loadasync.run();
}
@Override
public Object loadSync(AssetManager manager, String fileName, Fi file, AssetLoaderParameters parameter){
loadsync.run();
return super.loadSync(manager, fileName, file, parameter);
}
});
}else{
throw new IllegalArgumentException("Class already registered or loaded: " + type);
}
return load(name, type, null);
}
/**
* Loads a custom one-time 'asset' that knows how to load itself.
* @param load the asset
*/
public synchronized AssetDescriptor load(Loadable load){
if(getLoader(load.getClass()) == null){
setLoader(load.getClass(), new AsynchronousAssetLoader(Core.files::internal){
@Override
public void loadAsync(AssetManager manager, String fileName, Fi file, AssetLoaderParameters parameter){
load.loadAsync();
}
@Override
public Object loadSync(AssetManager manager, String fileName, Fi file, AssetLoaderParameters parameter){
load.loadSync();
return load;
}
@Override
public Seq<AssetDescriptor> getDependencies(String fileName, Fi file, AssetLoaderParameters parameter){
return load.getDependencies();
}
});
}
return load(load.getName(), load.getClass(), null);
}
/**
* Adds the given asset to the loading queue of the AssetManager.
* @param fileName the file name (interpretation depends on {@link AssetLoader})
* @param type the type of the asset.
* @param parameter parameters for the AssetLoader.
*/
public synchronized <T> AssetDescriptor<T> load(String fileName, Class<T> type, AssetLoaderParameters<T> parameter){
AssetLoader loader = getLoader(type, fileName);
if(loader == null) throw new ArcRuntimeException("No loader for type: " + type.getSimpleName());
// reset stats
if(loadQueue.size == 0){
loaded = 0;
toLoad = 0;
peakTasks = 0;
}
// check if an asset with the same name but a different type has already been added.
// check preload queue
for(int i = 0; i < loadQueue.size; i++){
AssetDescriptor desc = loadQueue.get(i);
if(desc.fileName.equals(fileName) && !desc.type.equals(type)) throw new ArcRuntimeException(
"Asset with name '" + fileName + "' already in preload queue, but has different type (expected: "
+ type.getSimpleName() + ", found: " + desc.type.getSimpleName() + ")");
}
// check task list
for(int i = 0; i < tasks.size; i++){
AssetDescriptor desc = tasks.get(i).assetDesc;
if(desc.fileName.equals(fileName) && !desc.type.equals(type)) throw new ArcRuntimeException(
"Asset with name '" + fileName + "' already in task list, but has different type (expected: "
+ type.getSimpleName() + ", found: " + desc.type.getSimpleName() + ")");
}
// check loaded assets
Class otherType = assetTypes.get(fileName);
if(otherType != null && !otherType.equals(type))
throw new ArcRuntimeException("Asset with name '" + fileName + "' already loaded, but has different type (expected: "
+ type.getSimpleName() + ", found: " + otherType.getSimpleName() + ")");
toLoad++;
AssetDescriptor assetDesc = new AssetDescriptor<>(fileName, type, parameter);
loadQueue.add(assetDesc);
return assetDesc;
}
/**
* Adds the given asset to the loading queue of the AssetManager.
* @param desc the {@link AssetDescriptor}
*/
public synchronized <T> AssetDescriptor<T> load(AssetDescriptor<T> desc){
return load(desc.fileName, desc.type, desc.params);
}
/**
* Updates the AssetManager, keeping it loading any assets in the preload queue.
* @return true if all loading is finished.
*/
public synchronized boolean update(){
try{
if(tasks.size == 0){
// loop until we have a new task ready to be processed
while(loadQueue.size != 0 && tasks.size == 0){
nextTask();
}
// have we not found a task? We are done!
if(tasks.size == 0) return true;
}
return updateTask() && loadQueue.size == 0 && tasks.size == 0;
}catch(Throwable t){
handleTaskError(t);
return loadQueue.size == 0;
}
}
/** @return the asset loading task that is currently being processed.
* May return null if nothing is being loaded. */
public synchronized AssetDescriptor getCurrentLoading(){
if(tasks.size > 0){
return tasks.first().assetDesc;
}
return null;
}
/**
* Updates the AssetManager continuously for the specified number of milliseconds, yielding the CPU to the loading thread
* between updates. This may block for less time if all loading tasks are complete. This may block for more time if the portion
* of a single task that happens in the GL thread takes a long time.
* @return true if all loading is finished.
*/
public boolean update(int millis){
long endTime = Time.millis() + millis;
while(true){
boolean done = update();
if(done || Time.millis() > endTime) return done;
Thread.yield();
}
}
/** Returns true when all assets are loaded. Can be called from any thread. */
public synchronized boolean isFinished(){
return loadQueue.size == 0 && tasks.size == 0;
}
/** Blocks until all assets are loaded. */
public void finishLoading(){
while(!update())
Thread.yield();
}
/**
* Blocks until the specified asset is loaded.
* @param assetDesc the AssetDescriptor of the asset
*/
public void finishLoadingAsset(AssetDescriptor assetDesc){
finishLoadingAsset(assetDesc.fileName);
}
/**
* Blocks until the specified asset is loaded.
* @param fileName the file name (interpretation depends on {@link AssetLoader})
*/
public void finishLoadingAsset(String fileName){
while(!isLoaded(fileName)){
update();
Thread.yield();
}
}
synchronized void injectDependencies(String parentAssetFilename, Seq<AssetDescriptor> dependendAssetDescs){
ObjectSet<String> injected = this.injected;
for(AssetDescriptor desc : dependendAssetDescs){
if(injected.contains(desc.fileName)) continue; // Ignore subsequent dependencies if there are duplicates.
injected.add(desc.fileName);
injectDependency(parentAssetFilename, desc);
}
injected.clear();
}
private synchronized void injectDependency(String parentAssetFilename, AssetDescriptor dependendAssetDesc){
// add the asset as a dependency of the parent asset
Seq<String> dependencies = assetDependencies.get(parentAssetFilename);
if(dependencies == null){
dependencies = new Seq();
assetDependencies.put(parentAssetFilename, dependencies);
}
dependencies.add(dependendAssetDesc.fileName);
// if the asset is already loaded, increase its reference count.
if(isLoaded(dependendAssetDesc.fileName)){
Class type = assetTypes.get(dependendAssetDesc.fileName);
RefCountedContainer assetRef = assets.get(type).get(dependendAssetDesc.fileName);
assetRef.count++;
incrementRefCountedDependencies(dependendAssetDesc.fileName);
}
// else add a new task for the asset.
else{
addTask(dependendAssetDesc);
}
}
/**
* Removes a task from the loadQueue and adds it to the task stack. If the asset is already loaded (which can happen if it was
* a dependency of a previously loaded asset) its reference count will be increased.
*/
private void nextTask(){
AssetDescriptor assetDesc = loadQueue.remove(0);
//Log.info("Loading asset task: {0}", assetDesc.fileName);
// if the asset not meant to be reloaded and is already loaded, increase its reference count
if(isLoaded(assetDesc.fileName)){
Class type = assetTypes.get(assetDesc.fileName);
RefCountedContainer assetRef = assets.get(type).get(assetDesc.fileName);
assetRef.count++;
incrementRefCountedDependencies(assetDesc.fileName);
if(assetDesc.params != null && assetDesc.params.loadedCallback != null){
assetDesc.params.loadedCallback.finishedLoading(this, assetDesc.fileName, assetDesc.type);
}
loaded++;
}else{
// else add a new task for the asset.
addTask(assetDesc);
}
}
/**
* Adds a {@link AssetLoadingTask} to the task stack for the given asset.
*/
private void addTask(AssetDescriptor assetDesc){
AssetLoader loader = getLoader(assetDesc.type, assetDesc.fileName);
if(loader == null)
throw new ArcRuntimeException("No loader for type: " + assetDesc.type.getSimpleName());
tasks.add(new AssetLoadingTask(this, assetDesc, loader, executor));
peakTasks++;
}
/** Adds an asset to this AssetManager */
public <T> void addAsset(final String fileName, Class<T> type, T asset){
// add the asset to the filename lookup
assetTypes.put(fileName, type);
// add the asset to the type lookup
ObjectMap<String, RefCountedContainer> typeToAssets = assets.get(type);
if(typeToAssets == null){
typeToAssets = new ObjectMap<>();
assets.put(type, typeToAssets);
}
typeToAssets.put(fileName, new RefCountedContainer(asset));
}
/**
* Updates the current task on the top of the task stack.
* @return true if the asset is loaded or the task was cancelled.
*/
private boolean updateTask(){
AssetLoadingTask task = tasks.peek();
boolean complete = true;
try{
complete = task.cancel || task.update();
}catch(RuntimeException ex){
task.cancel = true;
taskFailed(task.assetDesc, ex);
}
// if the task has been cancelled or has finished loading
if(complete){
// increase the number of loaded assets and pop the task from the stack
if(tasks.size == 1){
loaded++;
peakTasks = 0;
}
tasks.pop();
if(task.cancel) return true;
addAsset(task.assetDesc.fileName, task.assetDesc.type, task.getAsset());
// otherwise, if a listener was found in the parameter invoke it
if(task.assetDesc.params != null && task.assetDesc.params.loadedCallback != null){
task.assetDesc.params.loadedCallback.finishedLoading(this, task.assetDesc.fileName, task.assetDesc.type);
}
task.assetDesc.loaded.get(task.getAsset());
return true;
}
return false;
}
/**
* Called when a task throws an exception during loading. The default implementation rethrows the exception. A subclass may
* supress the default implementation when loading assets where loading failure is recoverable.
*/
protected void taskFailed(AssetDescriptor assetDesc, RuntimeException ex){
throw ex;
}
private void incrementRefCountedDependencies(String parent){
Seq<String> dependencies = assetDependencies.get(parent);
if(dependencies == null) return;
for(String dependency : dependencies){
Class type = assetTypes.get(dependency);
RefCountedContainer assetRef = assets.get(type).get(dependency);
assetRef.count++;
incrementRefCountedDependencies(dependency);
}
}
/**
* Handles a runtime/loading error in {@link #update()} by optionally invoking the {@link AssetErrorListener}.
*/
private void handleTaskError(Throwable t){
if(tasks.isEmpty()) throw new ArcRuntimeException(t);
// pop the faulty task from the stack
AssetLoadingTask task = tasks.pop();
AssetDescriptor assetDesc = task.assetDesc;
// remove all dependencies
if(task.dependenciesLoaded && task.dependencies != null){
for(AssetDescriptor desc : task.dependencies){
unload(desc.fileName);
}
}
// clear the rest of the stack
tasks.clear();
// inform the listener that something bad happened
if(listener != null){
listener.error(assetDesc, t);
}
if(assetDesc.errored != null){
assetDesc.errored.get(t);
}else{
throw new ArcRuntimeException(t);
}
}
/**
* Sets a new {@link AssetLoader} for the given type.
* @param type the type of the asset
* @param loader the loader
*/
public synchronized <T, P extends AssetLoaderParameters<T>> void setLoader(Class<T> type, AssetLoader<T, P> loader){
setLoader(type, null, loader);
}
/**
* Sets a new {@link AssetLoader} for the given type.
* @param type the type of the asset
* @param suffix the suffix the filename must have for this loader to be used or null to specify the default loader.
* @param loader the loader
*/
public synchronized <T, P extends AssetLoaderParameters<T>> void setLoader(Class<T> type, String suffix,
AssetLoader<T, P> loader){
if(type == null) throw new IllegalArgumentException("type cannot be null.");
if(loader == null) throw new IllegalArgumentException("loader cannot be null.");
ObjectMap<String, AssetLoader> loaders = this.loaders.get(type);
if(loaders == null) this.loaders.put(type, loaders = new ObjectMap<>());
loaders.put(suffix == null ? "" : suffix, loader);
}
/** @return the number of loaded assets */
public synchronized int getLoadedAssets(){
return assetTypes.size;
}
/** @return the number of currently queued assets */
public synchronized int getQueuedAssets(){
return loadQueue.size + tasks.size;
}
/** @return the progress in percent of completion. */
public synchronized float getProgress(){
if(toLoad == 0) return 1;
float fractionalLoaded = (float)loaded;
if(peakTasks > 0){
fractionalLoaded += ((peakTasks - tasks.size) / (float)peakTasks);
}
return Math.min(1, fractionalLoaded / (float)toLoad);
}
/**
* Sets an {@link AssetErrorListener} to be invoked in case loading an asset failed.
* @param listener the listener or null
*/
public synchronized void setErrorListener(AssetErrorListener listener){
this.listener = listener;
}
/** Disposes all assets in the manager and stops all asynchronous loading. */
@Override
public synchronized void dispose(){
clear();
Threads.await(executor);
}
/** Clears and disposes all assets and the preloading queue. */
public synchronized void clear(){
loadQueue.clear();
while(!update());
ObjectIntMap<String> dependencyCount = new ObjectIntMap<>();
while(assetTypes.size > 0){
// for each asset, figure out how often it was referenced
dependencyCount.clear();
Seq<String> assets = assetTypes.keys().toSeq();
for(String asset : assets){
dependencyCount.put(asset, 0);
}
for(String asset : assets){
Seq<String> dependencies = assetDependencies.get(asset);
if(dependencies == null) continue;
for(String dependency : dependencies){
int count = dependencyCount.get(dependency, 0);
count++;
dependencyCount.put(dependency, count);
}
}
// only dispose of assets that are root assets (not referenced)
for(String asset : assets){
if(dependencyCount.get(asset, 0) == 0){
unload(asset);
}
}
}
this.assets.clear();
this.assetTypes.clear();
this.assetDependencies.clear();
this.loaded = 0;
this.toLoad = 0;
this.peakTasks = 0;
this.loadQueue.clear();
this.tasks.clear();
}
/**
* Returns the reference count of an asset.
*/
public synchronized int getReferenceCount(String fileName){
Class type = assetTypes.get(fileName);
if(type == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
return assets.get(type).get(fileName).count;
}
/**
* Sets the reference count of an asset.
*/
public synchronized void setReferenceCount(String fileName, int refCount){
Class type = assetTypes.get(fileName);
if(type == null) throw new ArcRuntimeException("Asset not loaded: " + fileName);
assets.get(type).get(fileName).count = refCount;
}
/** @return a string containing ref count and dependency information for all assets. */
public synchronized String getDiagnostics(){
StringBuilder sb = new StringBuilder();
for(String fileName : assetTypes.keys()){
sb.append(fileName);
sb.append(", ");
Class type = assetTypes.get(fileName);
RefCountedContainer assetRef = assets.get(type).get(fileName);
Seq<String> dependencies = assetDependencies.get(fileName);
sb.append(type.getSimpleName());
sb.append(", refs: ");
sb.append(assetRef.count);
if(dependencies != null){
sb.append(", deps: [");
for(String dep : dependencies){
sb.append(dep);
sb.append(",");
}
sb.append("]");
}
sb.append("\n");
}
return sb.toString();
}
/** @return the file names of all loaded assets. */
public synchronized Seq<String> getAssetNames(){
return assetTypes.keys().toSeq();
}
/** @return the dependencies of an asset or null if the asset has no dependencies. */
public synchronized Seq<String> getDependencies(String fileName){
return assetDependencies.get(fileName);
}
/** @return the type of a loaded asset. */
public synchronized Class getAssetType(String fileName){
return assetTypes.get(fileName);
}
static class RefCountedContainer{
Object object;
int count = 1;
public RefCountedContainer(Object object){
if(object == null) throw new IllegalArgumentException("Object must not be null");
this.object = object;
}
}
}
+21
View File
@@ -0,0 +1,21 @@
package arc.assets;
import arc.struct.*;
public interface Loadable{
default void loadAsync(){
}
default void loadSync(){
}
default String getName(){
return getClass().getSimpleName();
}
default Seq<AssetDescriptor> getDependencies(){
return null;
}
}
@@ -0,0 +1,43 @@
package arc.assets.loaders;
import arc.assets.AssetDescriptor;
import arc.assets.AssetLoaderParameters;
import arc.struct.Seq;
import arc.files.Fi;
/**
* Abstract base class for asset loaders.
* @param <T> the class of the asset the loader supports
* @param <P> the class of the loading parameters the loader supports.
* @author mzechner
*/
public abstract class AssetLoader<T, P extends AssetLoaderParameters<T>>{
/** {@link FileHandleResolver} used to map from plain asset names to {@link Fi} instances **/
private FileHandleResolver resolver;
/**
* Constructor, sets the {@link FileHandleResolver} to use to resolve the file associated with the asset name.
*/
public AssetLoader(FileHandleResolver resolver){
this.resolver = resolver;
}
/**
* @param fileName file name to resolve
* @return handle to the file, as resolved by the {@link FileHandleResolver} set on the loader
*/
public Fi resolve(String fileName){
return resolver.resolve(fileName);
}
/**
* Returns the assets this asset requires to be loaded first. This method may be called on a thread other than the GL thread.
* @param fileName name of the asset to load
* @param file the resolved file to load
* @param parameter parameters for loading the asset
* @return other assets that the asset depends on and need to be loaded first or null if there are no dependencies.
*/
public Seq<AssetDescriptor> getDependencies(String fileName, Fi file, P parameter){
return null;
}
}
@@ -0,0 +1,31 @@
package arc.assets.loaders;
import arc.assets.AssetLoaderParameters;
import arc.assets.AssetManager;
import arc.files.Fi;
/**
* Base class for asynchronous {@link AssetLoader} instances. Such loaders try to load parts of an OpenGL resource, like the
* Pixmap, on a separate thread to then load the actual resource on the thread the OpenGL context is active on.
* @author mzechner
*/
public abstract class AsynchronousAssetLoader<T, P extends AssetLoaderParameters<T>> extends AssetLoader<T, P>{
public AsynchronousAssetLoader(FileHandleResolver resolver){
super(resolver);
}
/**
* Loads the non-OpenGL part of the asset and injects any dependencies of the asset into the AssetManager.
* @param fileName the name of the asset to load
* @param file the resolved file to load
* @param parameter the parameters to use for loading the asset
*/
public abstract void loadAsync(AssetManager manager, String fileName, Fi file, P parameter);
/**
* Loads the OpenGL part of the asset.
* @param file the resolved file to load
*/
public abstract T loadSync(AssetManager manager, String fileName, Fi file, P parameter);
}
@@ -0,0 +1,59 @@
package arc.assets.loaders;
import arc.assets.*;
import arc.files.*;
import arc.graphics.*;
import arc.util.*;
/**
* {@link AssetLoader} for {@link Cubemap} instances. The pixel data is loaded asynchronously. The texture is then created on the
* rendering thread, synchronously. Passing a {@link CubemapParameter} to
* {@link AssetManager#load(String, Class, AssetLoaderParameters)} allows one to specify parameters as can be passed to the
* various Cubemap constructors, e.g. filtering and so on.
* @author mzechner, Vincent Bousquet
*/
public class CubemapLoader extends AsynchronousAssetLoader<Cubemap, CubemapLoader.CubemapParameter>{
private static final String[] names = {"right.png", "left.png", "top.png", "bottom.png", "front.png", "back.png"};
final CubemapLoaderInfo info = new CubemapLoaderInfo();
public CubemapLoader(FileHandleResolver resolver){
super(resolver);
}
@Override
public void loadAsync(AssetManager manager, String fileName, Fi file, CubemapParameter parameter){
info.pixmaps = new Pixmap[6];
for(int i = 0; i < 6; i++){
info.pixmaps[i] = new Pixmap(file.sibling(file.nameWithoutExtension() + names[i]));
}
}
@Override
public Cubemap loadSync(AssetManager manager, String fileName, Fi file, CubemapParameter parameter){
if(info.pixmaps == null) return null;
Cubemap cubemap = parameter == null ? null : parameter.cubemap;
if(cubemap == null) cubemap = new Cubemap();
cubemap.load(info.pixmaps, parameter != null && parameter.mipmaps, true);
if(parameter != null){
cubemap.setFilter(parameter.minFilter, parameter.magFilter);
cubemap.setWrap(parameter.wrapU, parameter.wrapV);
}
return cubemap;
}
public static class CubemapLoaderInfo{
Pixmap[] pixmaps;
}
public static class CubemapParameter extends AssetLoaderParameters<Cubemap>{
/** The texture to put the data in, optional. **/
public @Nullable Cubemap cubemap = null;
public boolean mipmaps;
public TextureFilter minFilter = TextureFilter.nearest;
public TextureFilter magFilter = TextureFilter.nearest;
public TextureWrap wrapU = TextureWrap.clampToEdge;
public TextureWrap wrapV = TextureWrap.clampToEdge;
}
}
@@ -0,0 +1,25 @@
package arc.assets.loaders;
import arc.*;
import arc.assets.*;
import arc.files.*;
import arc.struct.*;
public abstract class CustomLoader extends AsynchronousAssetLoader{
public Runnable loaded = () -> {};
public CustomLoader(){
super(Core.files::internal);
}
@Override
public Object loadSync(AssetManager manager, String fileName, Fi file, AssetLoaderParameters parameter){
loaded.run();
return this;
}
@Override
public Seq<AssetDescriptor> getDependencies(String fileName, Fi file, AssetLoaderParameters parameter){
return null;
}
}
@@ -0,0 +1,13 @@
package arc.assets.loaders;
import arc.assets.AssetManager;
import arc.files.Fi;
/**
* Interface for classes the can map a file name to a {@link Fi}. Used to allow the {@link AssetManager} to load resources
* from anywhere or implement caching strategies.
* @author mzechner
*/
public interface FileHandleResolver{
Fi resolve(String fileName);
}

Some files were not shown because too many files have changed in this diff Show More